我在Tkinter / Python中创建了一个十问题多项选择测验。我创建了一个类来存储所有按钮,然后创建一个其他类来存储出现在子窗口中的每个问题,并将问题作为标签和radiobuttons / checkbuttons。对于每个问题,当用户按下“Enter”时,程序会将他们的选择与正确的回答者进行比较,并在必要时添加1分。如何使变量“Score”可用于程序中的所有内容(即每个类)?我是否必须在课程之间传递分数值?
class Question_5_Window(tk.Toplevel):
'''A simple instruction window'''
def __init__(self, parent):
tk.Toplevel.__init__(self, parent)
self.text = tk.Label(self, width=100, height=4, text = "5) What would you do if you were walking to class and you saw a first year crying? Tick all correct answers.")
self.text.pack(side="top", fill="both", expand=True)
question_5_Var1 = IntVar()
question_5_Var2 = IntVar()
question_5_Var3 = IntVar()
A_5 = Checkbutton(self, text = "Keep walking", variable = question_5_Var1, onvalue = 1, offvalue = 0, height=5, width = 20)
A_5.pack()
B_5 = Checkbutton(self, text = "Take them to guidance", variable = question_5_Var2, onvalue = 1, offvalue = 0, height=5, width = 20)
B_5.pack()
C_5 = Checkbutton(self, text = "Talk to them to resolve issue", variable = question_5_Var3, onvalue = 1, offvalue = 0, height=5, width = 20)
C_5.pack()
def calculate_score():
if (question_5_Var2.get() == 1) and (question_5_Var3.get() == 1) and not question_5_Var1.get():
print("calculate score has worked")
score = score + 1
else:
print("not worked")
return score
Enter_5 = Button(self, text= "Enter", width=10, command = calculate_score)
Enter_5.pack()
return score
答案 0 :(得分:4)
根据我们的讨论,获得所需内容的最快方法是在包含问题按钮的tk对象中添加属性。
class WhateverContainer(tk.Frame):
def __init__(self) # ... *args, **kwargs or whatever is appropriate
# ... other stuff
self.scores = dict() # common storage
class Question(tk.TopLevel):
def __init__(self, parent, question_id): # ... whatever arguments
# ...
def callback()
if nice_answer:
parent.scores[question_id] = 1
要清楚,这不是一个“好”的解决方案,因为至少,子窗口不应该直接弄乱父级的数据。但是,我认为它适用于您的应用程序。如果您想获得有关您的设计和编码的反馈,您可能会对CodeReview感到幸运。
我希望这个测验适合你。
答案 1 :(得分:0)
另一种实现此目的的方法是在主模块中声明一个Tkinter控件变量(在你的情况下是一个IntVar,因为它处理测验得分),然后使这个相同的控件变量成为每个需要共享的类的属性/更新它。执行此操作时,每个类都可以使用IntVar的get / set方法,并且所有更新都会继续执行其他类(以及主模块)。
我写了一个简短的演示程序,我称之为“tripwire”,以证明这是有效的:
import Tkinter as tk
#Clumsy thief who crosses the tripwire
#The twVar is a Tkinter IntVar
class Thief1:
def __init__(self,twVar):
self.twVar = twVar
def cross(self):
self.twVar.set(1)
#Second thief who silences the alarm
#The twVar here is the same one as Thief1
class Thief2:
def __init__(self,twVar):
self.twVar = twVar
def silence(self):
self.twVar.set(0)
#Main module
root = tk.Tk()
#Declare and initialize the IntVar
ctrlTW = tk.IntVar()
ctrlTW.set(0)
#Instantiate each class, using the same
#IntVar for each
t1 = Thief1(ctrlTW)
t2 = Thief2(ctrlTW)
#Now call each thief's method
print 'Initial value: '+str(ctrlTW.get())
t1.cross()
print 'After Thief #1: '+str(ctrlTW.get())
t2.silence()
print 'After Thief #2: '+str(ctrlTW.get())
这种技术的一个很好的好处是你可以使用控制变量的观察者在任何类使用该值执行某些操作时执行回调。这(部分)解决了KobeJohn关于让孩子窗口弄乱父母数据的担忧。回调允许主模块至少监视每个类对共享数据的作用并做出相应的反应。
#Main module with trace and callback added
root = tk.Tk()
def twObserve(*args):
if (ctrlTW.get()):
print 'Hey! Intruder detected!'
else:
print 'Oh... never mind.'
#Declare and initialize the IntVar
ctrlTW = tk.IntVar()
ctrlTW.set(0)
#Set the callback for updates
ctrlTW.trace('w',twObserve)
#Instantiate each class, using the same
#IntVar for each
t1 = Thief1(ctrlTW)
t2 = Thief2(ctrlTW)
#Now call each thief's method. The callback
#will activate with each update.
t1.cross()
t2.silence()