在Tkinter中遍历小部件
我在想一个问题:
我在界面上有很多相似的小部件,比如标签(Labels)。我在算法的每次迭代中都会更新它们(在相关的函数中使用 root.update()
)。我想知道,怎么才能遍历每一个标签。
当然,这些标签是用类似下面的方式创建的:
self.var1=IntVar()
self.lab1=Label(frame,textvariable=self.var1)
self.lab1.grid()
所以每个标签的名字是 lab1、lab2,等等。我觉得应该有更好的命名方式,这样我就不需要一个个地调用每个名字,或者可以用某种方法来遍历它们。
3 个回答
0
上面的回答并没有完全按照我想要的方式工作,所以我在Python 3.11中通过递归的方式查看了一个窗口/框架的所有子元素:
def IterateWindowWidgets(window):
for widget in window.winfo_children():
lastDot = str(widget).rfind('.')
# The format of str(widget) is '!window.!frame.!widget', so this is to only
# look at the lowest current widget in the hierarchy.
if '!toplevel' in str(widget)[lastDot:] or '!frame' in str(widget)[lastDot:]:
IterateWindowWidgets(widget)
else:
if '!label' in str(widget)[lastDot:]
widget.yourCommandHere
14
你一致的命名规则让你可以用变量名来遍历你的变量:
for i in range(1,n):
label = getattr(self, "lab"+str(i))
你也可以考虑使用Tkinter,它会保留一个树状结构的控件,这些控件可以通过children
这个属性(一个字典)来访问:
for child in frame.children.values():
#do something to all children
如果你的框架里包含其他控件,最后你可能还需要添加一些过滤功能。例如,可以根据控件的类别进行过滤:
for label in filter(lambda w:isinstance(w,Label), frame.children.itervalues()):
#do something on labels
需要注意的是,children里的内容并不能保证遍历的顺序。如果你需要这样的功能,可以依赖几何管理器的信息,比如pack_slaves
或grid_slaves
:
for child in frame.pack_slaves():
#traverse in pack addition order
#or
for child in reversed(frame.grid_slaves()):
#traverse in grid addition order
1
最简单的方法是把每个小部件的引用存放在一个列表或字典里,而不是(或者说也可以)用单独的实例变量来存储。