我是Python新手,一直在做一个学校的项目。这个想法是参加酒精使用障碍识别测试(AUDIT),让用户知道他是否应该寻求专业帮助(如果他的分数是14+)。我今天被卡住了。我正在使用tkinter,以及一套10个带有radiooboxes的问题。然而,我无法继续进行,因为问题不适合在屏幕上,而且看在上帝的份上,我不能让它滚动。我已经尝试了所有我能找到的方法,设置一个类,尝试使用一个框架或画布,等等。
"""imports"""
import tkinter as tk
app = tk.Tk()
app.title("AUDIT")
from tkinter import *
from tkinter import ttk
canvas = tk.Canvas(app)
scroll_y = tk.Scrollbar(app, orient="vertical", command=canvas.yview)
frame = tk.Frame(canvas)
# group of widgets
"""question 1"""
o1 = Text(app, height = 1, width =100)
o1.insert(INSERT, "Jak často pijete alkoholické nápoje (včetně piva)")
o1.insert(END, "?")
o1.pack()
OTAZKA1 = [
("Nikdy", "0"),
("Jednou za měsíc či méně často", "1"),
("2-4x za měsíc", "2"),
("2-3x týdně", "3"),
("4x nebo vícekrát týdně", "4"),
]
o1 = StringVar()
o1.set("0") #initialize
for text, mode in OTAZKA1:
a = Radiobutton(app, text = text, variable = o1, value = mode)
a.pack(anchor=W)
"""question 2"""
o2 = Text(app, height = 2, width =100)
o2.insert(INSERT, "Kolik standardních sklenic alkoholického nápoje vypijete během typického dne, kdy pijete")
o2.insert(END, "?")
o2.pack()
OTAZKA2 = [
("Nejvýše 1", "0"),
("1,5 až 2", "1"),
("2,5 až 3", "2"),
("3,5 až 5", "3"),
("5 a více", "4"),
]
o2 = StringVar()
o2.set("0") #initialize
for text, mode in OTAZKA2:
b = Radiobutton(app, text = text, variable = o2, value = mode)
b.pack(anchor=W)
一直到第10题 我知道这可能不是最有效的方法,但这是我写的第一段代码。我怎样才能添加滚动条使所有的问题都可见?
你需要 1)使用 Canvas.create_window(x, y, window=widget)
方法2)设置画布 scrollregion
归于 Canvas.bbox("all")
但在此之前必须更新窗口,否则会得到错误的结果 "3)用正确的方法将滚动条连接到画布上(见下面的代码)。
我也可以给你一些建议:1)GUI最好用OOP。对于小的应用来说,可能不是问题,但是如果你的应用比较复杂,比较大,你用OOP的代码,会比用程序化的代码要容易很多。2)你是否注意到你的代码有很多相似的部分?记住:在几乎所有的情况下,都不需要手动创建很多类似的变量(也就是所谓的? DRY原则(不重复). 你可以使用循环自动生成一切。有时你需要使用 enumerate
从Python内置的函数。如果你不会使用DRY原则,你会为开发花费更多的时间。 3)最好避免通过导入其他模块来覆盖已经导入的东西。在你的代码中,你是这样做的。
from tkinter import *
from tkinter.ttk import *
既要 这些模块中包含 Button
, Entry
, Scrollbar
, Radiobutton
等。所以你可能会把所有的东西都弄混。最好是这样做。
from tkinter import *
from tkinter.ttk import only, what, you, need
或者甚至更好。
import tkinter as tk
import tkinter.ttk as ttk # or: from tkinter import ttk
4) 你可以手动调整Canvas中所有东西的大小,并拒绝调整窗口的大小(无论是宽度还是高度)。
下面是重写的代码。
from tkinter import *
from tkinter import messagebox
from tkinter.ttk import Button, Scrollbar, Radiobutton
# Create questions as a list of dictionaries
# The GUI will be generated automatically
questions = [
{"question": "Jak často pijete alkoholické nápoje (včetně piva)?",
"answers": ("Nikdy", "Jednou za měsíc či méně často",
"2-4x za měsíc", "2-3x týdně",
"4x nebo vícekrát týdně")},
{"question": "Kolik standardních sklenic alkoholického nápoje vypijete během typického dne, kdy pijete?",
"answers": ("Nejvýše 1", "1,5 až 2", "2,5 až 3", "3,5 až 5", "5 a více")},
]
class App(Tk):
def __init__(self):
super().__init__()
self.title("AUDIT") # set the window title
self.resizable(False, True) # make window unresizable by width
canv_frame = Frame(self) # create the canvas frame
# create the Canvas widget
# highlightthickness=0 removes the black border when the canvas gets focus
self.canv = Canvas(canv_frame, highlightthickness=0, width=420)
# add scrolling when mouse wheel is rotated
self.canv.bind_all("<MouseWheel>",
lambda event: self.canv.yview_scroll(-1 * (event.delta // 120), "units"))
self.canv.pack(fill=BOTH, expand=YES, side=LEFT) # pack the Canvas
# Create a scrollbar
# command=self.canv.yview tells the scrollbar to change the canvas yview
# and canvas's yscrollcommand=self.yscrollbar.set tells the canvas to update
# the scrollbar if canvas's yview is changed without it.
self.yscrollbar = Scrollbar(canv_frame, command=self.canv.yview)
self.canv["yscrollcommand"] = self.yscrollbar.set
self.yscrollbar.pack(fill=Y, side=LEFT) # pack the Scrollbar
for question_id, question in enumerate(questions, 1):
qaframe = Frame(self.canv) # create the question-answers (QA) frame
text = Text(qaframe, width=50, height=3) # create the Text widget for question
text.insert(END, question["question"]) # insert the question text there
text.pack(fill=X) # pack the text widget
aframe = Frame(qaframe) # create the answers frame
# Create the question variable and add it to the variables list
question_var = IntVar(self)
question["variable"] = question_var
# create the radiobuttons
for answer_id, answer in enumerate(question["answers"]):
Radiobutton(aframe, variable=question_var, text=answer, value=answer_id).pack()
aframe.pack(fill=Y) # pack the answers frame
self.canv.create_window(210, question_id * 175, window=qaframe) # insert the QA frame into the Canvas
canv_frame.pack(fill=BOTH, expand=YES) # pack the canvas frame
Button(self, text="Submit", command=self.submit).pack(fill=X) # create the "Submit" button
self.update() # update everything to get the right scrollregion.
self.canv.configure(scrollregion=self.canv.bbox("all")) # set the canvas scrollregion
def submit(self):
sum_ = 0 # initially, the sum_ equals 0
for question in questions:
sum_ += question["variable"].get() # and then, we add all the questions answers
messagebox.showinfo("Result", "Your result is %s!" % sum_) # show the result in an info messagebox
if __name__ == "__main__": # if the App is not imported from another module,
App().mainloop() # create it and start the mainloop