在Tkinter中遍历小部件

5 投票
3 回答
10316 浏览
提问于 2025-04-17 09:38

我在想一个问题:

我在界面上有很多相似的小部件,比如标签(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_slavesgrid_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

最简单的方法是把每个小部件的引用存放在一个列表或字典里,而不是(或者说也可以)用单独的实例变量来存储。

撰写回答