【问题标题】:How to call a function whenever global variable changes it value?每当全局变量更改其值时如何调用函数?
【发布时间】:2017-06-06 11:10:51
【问题描述】:

当全局变量a 更改其值时,我如何调用函数change_label?使用change_variable,我正在尝试模拟变量的实际变化(单击按钮时变量会发生变化)。

from tkinter import *

a = 3

class Application(Frame):

    def __init__(self, master):
        Frame.__init__(self, master)
        self.master = master
        self.button = Button(self.master, text='Change Variable', command=self.change_variable)
        self.button.grid(row=0)
        self.label = Label(self.master, text='Test')
        self.label.grid(row=1)

    def change_label(self):
        self.label.config(bg='Red', fg='Yellow')

    def change_variable(self):
        global a
        a = 1

def main():
    root = Tk()
    Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

【问题讨论】:

  • 如果没有问题,可以使用轻量级线程定期监控值。
  • 好吧,你为什么不在所有改变a的地方打电话给change_label
  • 为什么不在对象上使用属性而不是全局属性,那么您可以从 setter 调用您的函数。

标签: python tkinter


【解决方案1】:

如果您使用 tkinter 特殊变量之一(StringVar 等),您可以添加一个“跟踪”,该跟踪将在设置或取消设置变量时触发回调。

例如:

class Application(Frame):

    def __init__(self, master):
        Frame.__init__(self, master)
        ...
        self.a = tk.IntVar(value=3)
        self.a.trace("w", self.change_label)
        ...

    def change_label(self, *args):
        self.label.config(bg='Red', fg='Yellow')

    def change_variable(self):
        self.a.set(1)

这样,每当您通过set 方法设置self.a 的值时,将调用与trace 绑定的函数。

任何使用该变量的小部件也将被更新。例如,将您的标签更改为:

self.label = tk.Label(self.master, textvariable=self.a)

当您单击按钮时,请注意标签会发生变化以反映变化。

有关传递给跟踪函数的参数的说明,请参阅What are the arguments to Tkinter variable trace method callbacks?

这些变量在这里有很好的描述:The Variable Classes (BooleanVar, DoubleVar, IntVar, StringVar)

【讨论】:

    【解决方案2】:

    如果您使用的是Tk,这可能值得研究:Tk's "Variable" classes

    如果这对你不起作用(因为你想存储自己的类型,或类似的东西),Shiva 的评论是要走的路,如果你想存储多个变量,这可能是个好主意:

    class Storage(dict):
        def __getattribute__(self, name):
            return self[name]
    
        def __setattr__(self, name, value):
            print(name, value)  # react to the change of name
            self[name] = value
    
    storage = Storage({a: 3, b: 2})
    
    storage.a = 4
    print(storage.a)
    

    如果您不想在不触发您放在那里的一些代码的情况下设置变量,那么祝您好运。您也可以覆盖__setitem__,但您始终可以使用Storage 变量作为第一个参数调用dict.__setitem__

    【讨论】:

      【解决方案3】:

      尝试运行这段代码,它会让你知道你想要什么。

      import tkinter
      count = 5
      def change_text():
              global count
              if count != 2:
                      button.config(text='edit')
      
      frame = tkinter.Frame(height=500,width=500)
      button = tkinter.Button(frame,text='save',command=change_text)
      button.place(x=0,y=0)
      frame.pack()
      frame.mainloop()
      

      【讨论】:

        【解决方案4】:
        The code was supposed be like this.
        from tkinter import *
        
        a = 3
        
        class Application(Frame):
        
            def __init__(self, master):
                Frame.__init__(self, master)
                self.master = master
                self.button = Button(self.master, text='Change Variable', command=self.change_label)
                self.button.grid(row=0)
                self.label = Label(self.master, text='Test')
                self.label.grid(row=1)
        
            def change_label(self):
                global a
                a = 1
                if a != 3:
                    self.label.config(bg='Red', fg='Yellow')
        
        def main():
            root = Tk()
            Application(root)
            root.mainloop()
        hope that is what you wanted.
        

        【讨论】:

        • 为什么要添加第二个答案? “代码应该是这样的”是什么意思?您知道您可以编辑原始答案吗?
        • 您不需要 change_variable 方法,您仍然可以使用 change_variable 方法完成的所有操作。
        猜你喜欢
        • 1970-01-01
        • 2020-09-04
        • 1970-01-01
        • 2021-07-12
        • 2017-10-22
        • 1970-01-01
        • 2020-04-29
        • 1970-01-01
        • 2021-03-12
        相关资源
        最近更新 更多