当StringVar添加到窗口小部件时,TKinter-是StringVar.trace吗?

时间:2015-01-28 15:27:18

标签: python python-3.x tkinter trace

我有一个使用Tkinter的程序,该程序使用多个StringVar来跟踪多个窗口上的数据。我一直在使用

myStringVar.trace('w', lambda *args: update())

检测用户何时更改其中一个变量,通过与条目交互或从OptionMenu中选择选项,其中'update'是一个根据需要更改GUI的其他部分的函数和'root '是的。但是,我发现update()在我的代码的特定行中被myStringVar.trace()调用:

name = OptionMenu(self, self.source, self.source.get(), *root.namelist)

其中self.source是有问题的StringVariableroot.namelist是普通的列表。我通过将上面的行夹在两个跟踪语句之间并将trace语句添加到我的更新函数中来发现这一点。我还确认用

替换上面的行
name = Entry(self, textvariable=self.source)

不会有相同的结果。

尽可能多地复制原始代码的形式,我编写了以下测试代码:

from tkinter import *

root = Tk()
root.myStringVar = StringVar(root)
root.myStringVar.set('hello')

class myFrame(Frame):
    def __init__(self, root):
        Frame.__init__(self, root)
        self.source = root.myStringVar
        self.update()
        self.pack()
    def update(self):
        for widget in self.winfo_children(): widget.destroy()
        name = OptionMenu(self, self.source, self.source.get(), '1','2','3')
        name.pack()

root.myframe = myFrame(root)
root.myStringVar.get()

def speak(root):
    print(root.myStringVar.get())
    root.myframe.update()
root.myStringVar.trace('w', lambda *args: speak(root))

mainloop()

但是,当我运行此代码时,除非我按照您的预期更改OptionMenu中的选项,否则它不会打印任何内容。

我能想到的两种情况之间的唯一区别是,在我的测试代码中,放置OptionMenu的帧是静态的,而在我的实际代码中它是动态生成的,但我看不到这将如何影响处理OptionMenu的创建方式。

2 个答案:

答案 0 :(得分:0)

要回答您的特定问题“当StringVar添加到窗口小部件时,TKinter-是StringVar.trace吗?”,答案是“否”。将stringvar添加到窗口小部件时,不会调用跟踪。跟踪 - 假设它是写跟踪 - 仅在变量值更改时调用。

问题可能是由于您正在创建名为update的方法。这是一种已存在于小部件上的方法,可能由各种tkinter函数在内部调用。尝试将您的函数重命名为其他内容(例如:update_widget)。

答案 1 :(得分:0)

也许我没有抓住你的意思。它对我很有用,也许你忘了打印:

[...]
root.myframe = myFrame(root)
#this print myStringVar content even when the value doesn't change (each time you call it):
print("main:", root.myStringVar.get()) #<-- this is the missing print, i guess

def foo(*args): #custom useless function
    """Prints "hello" each time OptionMenu selection change"""
    print("foo: hello")

def showargs(*args): #show params, useless too
    """Prints args content each time OptionMenu change"""
    print("showargs:", args)

def showcontent(*args): #finally this print myStringVar content
    """Prints myStringVar content each time OptionMenu change"""
    print("showcontent: ",root.myStringVar.get())

root.myStringVar.trace('w', foo)
root.myStringVar.trace('w', showargs)
root.myStringVar.trace('w', showcontent)
#output:
#main: hello
#after user select "1" from OptionMenu:
#showcontent:  1
#showargs: ('PY_VAR0', '', 'w')
#foo: hello

我添加了三个调试方法来测试myStringVar内容:

  • foo没用,但每次用户更改OptionMenu值时都会触发,

  • showargs显示* args param内容,

  • showcontent显示myStringVar内容。

  • 如果你因为第19行而被卡住了,你会忘记将它打印到控制台或以某种方式显示gui(我添加了一个打印件)并且它有效。

因此,您可以传递myStringVar并获取其内容和/或显示对其的任何更改。