Looping over widgets in Tkinter
Asked Answered
M

3

5

here's the issue I'm thinking of:

I have a number of similar widgets in the frame(e.g. Lables). I update them every iteration of the algorithm (using root.update() in the relevant function. What I'd like to know, is how to loop through each Label.

Of course, they were created with something like

self.var1=IntVar()
self.lab1=Label(frame,textvariable=self.var1)
self.lab1.grid() 

So each of the lables are named lab1,lab2, etc. I'm quite sure there should either be a better way of naming them, so that I don't have to call each name explicitly, or somehow loop though them.

Megrim answered 5/1, 2012 at 23:29 Comment(0)
D
2

The easiest way is to store references to each widget in a list or dictionary rather than (or in addition to) scaler instance variables.

Defray answered 6/1, 2012 at 0:34 Comment(2)
you mean something like list1=[self.var1,self.var2] and then loop through list1[list]?Megrim
I know this is old, but it just saved me a ton of time.Trumpetweed
N
14

Your consistant name scheme let you use the variable name to iterate through your variables:

for i in range(1,n):
    label = getattr(self, "lab"+str(i))

You may also consider relying on Tkinter whom retain a tree structure of your widgets accessible through children widget attribute (a dictionary):

for child in frame.children.values():
    #do something to all children

And eventually add some filtering if your frame contains other widgets. For instance, to filter on classes of widgets:

for label in filter(lambda w:isinstance(w,Label), frame.children.itervalues()):
    #do something on labels

Note that children does not have any guarantee on order traversal. For such service, you may rely on geometry manager infos, ie pack_slaves or 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
Neubauer answered 9/1, 2012 at 12:27 Comment(0)
D
2

The easiest way is to store references to each widget in a list or dictionary rather than (or in addition to) scaler instance variables.

Defray answered 6/1, 2012 at 0:34 Comment(2)
you mean something like list1=[self.var1,self.var2] and then loop through list1[list]?Megrim
I know this is old, but it just saved me a ton of time.Trumpetweed
B
0

The above answers did not work exactly as I wanted them to, and so I have done this in Python 3.11 by recursively looking through all children of a window/frame:

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
Bobstay answered 15/8, 2023 at 15:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.