通过实例引用 tkinter 小部件

Refer to tkinter widget by its instance

我正在学习 Python w/ Tkinter,我最近了解了小部件的引用和 name/instance 之间的区别。引用是您分配给小部件的字符串(稍后可以更改),但名称似乎是小部件的实际标识(不可变)。从本质上讲,该引用似乎是一个小部件的昵称,因为它会随着时间的推移而变化,并且会根据您与谁交谈而有所不同,而小部件的驾驶执照上的小部件的实际名称始终是相同的。具体来说,在这行代码中...

sample_frame = Frame(root, name = 'frame1', bg = 'blue', height = 50, width = '50')

"sample frame" 是引用,而 'frame1' 是名称。

除非我特别指定字符串'frame1'作为这个框架的名称,否则python会自动生成一个数字序列作为它的名称。要查看任何小部件的名称,您只需添加...

print(str(sample_frame))

(the output in this example is .frame1)

所以在 Tkinter 中,如果我想将这个框架放在我的 GUI 中,我将不得不 pack/grid/place 在下一行中像这样...

sample_frame.pack()

但我想做的是通过其 name 而不是其 reference 调用此框架小部件上的 pack 方法。像这样...

frame1.pack() #or
.frame1.pack() #because of that period

问题是 Python 声称 frame1 从未定义,并且 .frame1 是无效语法。有谁知道如何做这样的事情?谢谢

为了更广泛的上下文,我这样做是因为我迭代创建了 21 个不同的帧并将它们放置在 3x7 网格中。因此,所有 21 帧都有相同的 reference。但是,我确保每个帧的 name 与其位置相对应。

name= 选项在实际实现 GUI 的 Tcl 环境中设置小部件的名称 - 它对 Python 端没有影响。我能想到的这样做的唯一原因是它可能使 Tcl 错误消息更容易阅读(否则你会得到的自动生成的小部件名称并不是特别有意义)。

与往常一样,处理循环中创建的多个对象的正确方法是将它们存储在某种容器中。在您的情况下,它可能是一个 21 元素列表、一个嵌套列表 (widget[row][column]),或者可能是一个由元组 (widget[row, column]) 索引的字典。

虽然我完全同意 that you should keep a proper reference to the widgets and I do not recommend using what I'm about to explain, there actually is a way to achieve what you're asking. There's a widget method called nametowidget(),但 returns 当您给小部件对象命名时。请注意,您应该在包含您要查找的小部件的对象 (TkToplevelFrame) 上调用该方法。

所以按照你的例子,这是可行的:

from tkinter import *
root = Tk()
sample_frame = Frame(root, name = 'frame1', bg = 'blue', height = 50, width = '50')
root.nametowidget('frame1').pack()
root.mainloop()

如果你想对框架内的按钮做同样的事情,你应该这样做:

sample_button = Button(sample_frame, text='Button', name='button1')
sample_frame.nametowidget('button1').pack()