在将StringVar添加到小部件时,是否调用了TKinter StringVar.trace?

2024-05-09 11:43:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个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是所讨论的StringVariable,而root.namelist是一个普通列表。我把上面的一行夹在两个跟踪语句之间,并在update函数中添加一个跟踪语句,就发现了这一点。我还确认用

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的创建的方式。


Tags: lambda代码nameselfsourcegetdef选项
2条回答

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

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

也许我没明白你的意思。对我来说很管用,也许你忘了打印:

[...]
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参数内容,

  • showcontent显示myStringVar内容。

  • 如果因为在第19行显示结果而陷入困境,则会忘记将其打印到控制台或以某种方式显示给gui(我添加了一个打印),这样就可以工作了。

所以您可以传递myStringVar并获取其内容和/或显示其任何更改。

相关问题 更多 >