offeltoffel
offeltoffel

Reputation: 2801

Python Tkinter: How to config a button that was generated in a loop?

I am using Python 2.7 and Tkinter to make a GUI for my code. At one point, a frame is filled with many buttons in a loop. When I click on one of the buttons, the function needs to know from where it was called, so I googled and found out this nice way to do it:

def generate_buttons(n):
    for i in xrange(n):
        newbutton = str(i)
        newbutton = Button(myFrame, text=newbutton, command= lambda name=i:print_name(name)).grid(column=i)

and:

def print_name(name):
    print name

So when I generate my buttons like this:

generate_buttons(5)

the 5 buttons appear in one row. If I click on number 3, console prints "3".

Now what do I do if I want to further access the buttons. For example give them a new appearence. If I created just one button, it would be easy:

myButton.Button(text="bla")
myButton.config(relief=SUNKEN)

or

myButton.config(padx=10)

But in the loop, I override "newbutton" all the time. Does that mean I cannot get access to the individuals anymore? How do I "address" an object that was iteratively created and thus does not have a name?

Upvotes: 1

Views: 20510

Answers (1)

CommonSense
CommonSense

Reputation: 4482

Use a structure (a list or a dictionary) to hold your objects. The main difference between those two options - with a list, your logic to access theese objects is stricted to indexes only, while with dictionary a key parameter can be anything (and index too). If you need something to read about structures - take a look on python docs.

There's a snippet with a list:

try:
    import tkinter as tk
except ImportError:
    import Tkinter as tk


def generate_buttons(n):
    for _ in range(n):              #   xrange in python 2
        newbutton = tk.Button(text=_, command=lambda name=_: change_relief(name))
        newbutton.grid(column=_)
        buttons.append(newbutton)


def change_relief(idx):
    button = buttons[idx]

    if button['relief'] == 'raised':
        button.config(relief='sunken')
    else:
        button.config(relief='raised')


root = tk.Tk()

#   our list with buttons
buttons = []

#   generate some buttons
generate_buttons(5)

#   another button, that uses a value from an entry below
change_relief_button = tk.Button(text='Change relief by id',
                                 command=lambda: change_relief(int(id_entry.get())))
change_relief_button.grid()

#   entry with user input
id_entry = tk.Entry()
id_entry.grid()

#   default 0
id_entry.insert(0, '0')

#   mainloop
root.mainloop()

Each of numbered buttons able to change it's own relief, while the `change_relief_button' changes a relief of a button by index from an entry.

Upvotes: 2

Related Questions