1

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?

offeltoffel
  • 2,691
  • 2
  • 21
  • 35
  • 3
    Populate a `list` or a `dict` object with them. – CommonSense Jun 16 '17 at 11:30
  • You can see a similar question, asked yesterday, [here](https://stackoverflow.com/questions/44559203/issue-while-setting-value-to-tkinter-entry-widget-within-for-loop/44561678). – CommonSense Jun 16 '17 at 11:33
  • I am not quite familiar with dicts, so I tried to do it with a list. In the function I declared: global newbutton; outside the function I initialized the list with: newbutton = [None] * 5; then populated it by calling the function: generate_buttons(5); and when I do: newbutton[2].config(...) it says "AttributeError: 'NoneType' object has no attribute 'config'" – offeltoffel Jun 16 '17 at 12:02
  • [`grid` function returns None](https://stackoverflow.com/a/1101765/6634373). – CommonSense Jun 16 '17 at 12:31

1 Answers1

2

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.

CommonSense
  • 4,232
  • 2
  • 14
  • 38
  • Thank you for your fantastic help! At first I thought your method was limited to changing relief only, since the change_relief()-command was called right when the button is created, but I experimented with your solution a bit and found nice ways to use it for my own purpose. I think the helpful trick is to create the button-list outside, but append the items inside the function. – offeltoffel Jun 16 '17 at 13:54
  • 1
    @offeltoffel, yeah, exactly! I sticked to `relief` option only because it was mentioned in your question. Forgot to mention that you can interact with `button` in any way you want it (obiviously), hence this snippet is just a example. Glad, if it really helped you. – CommonSense Jun 16 '17 at 14:02