【问题标题】:How do I pass a value between classes in tkinter?如何在 tkinter 的类之间传递值?
【发布时间】:2014-01-05 08:05:50
【问题描述】:

我在 Tkinter/Python 中创建了一个十题多项选择测验。我创建了一个类来存储所有按钮,然后创建了十个其他类来存储出现在子窗口中的每个问题,该问题作为标签和单选按钮/复选按钮。对于每个问题,当用户按下“Enter”时,程序会将他们的选择与正确的回答者进行比较,并在必要时加 1 分。如何使变量“分数”可用于程序中的所有内容(即每个班级)?我必须在类之间传递分数的值吗?

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

【问题讨论】:

  • 你有示例代码吗?
  • 是的,我已经编辑了问题
  • @user3056786 我认为这需要一些讨论/修订/编辑。任何想帮忙的人,也许你可以使用this chat room
  • @user3056786 如果它对您有用,请接受答案,或者更新无效的内容,以便解决这个问题。如果您希望您的问题对与您有类似问题的其他人有所帮助,您可能希望更新您的问题以遵循我们讨论的指南。
  • 是的,您提供的解决方案 DID 工作

标签: python class variables tkinter


【解决方案1】:

根据我们的讨论,获得所需内容的最快方法是向包含问题按钮的 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 获得一些运气。

我希望测验对你很有效。

【讨论】:

    【解决方案2】:

    实现此目的的另一种方法是在主模块中声明一个 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-03
      • 1970-01-01
      • 1970-01-01
      • 2014-01-15
      • 2011-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多