[Tutor] Shortening the code

Peter Otten __peter__ at web.de
Sat Nov 26 13:20:41 CET 2011


Mic wrote:

[Alan Gauld]
> >def create_widgets(self):
>       >list_chair=[(0, 0, '01'), (0, 1, '02'),
>                   (0, 3, '03'), (0, 4, '04'),
>                   (1, 0, '05')]
>       >for row, column, name in list_chair:
>          >command = partial(button_clicked, button)
>          >button = tk.Button(self, color='green',
>                             >command=command, text=name)
>          >button.grid(row=row, column=column)

[Mic]
> This solution was better than mine since it is possible
> to place the widgets where you want, which I couldn't do.
> 
> 
> So, using your suggestions I get this:
> 
> import tkinter as tk
> from functools import partial
> 
> def button_clicked(button):
>     if button["bg"] == "green":
>         button.configure(bg="red")
>     else:
>         button.configure(bg="green")
> 
> class Window(tk.Frame):
>     def __init__(self, master):
>         super (Window, self).__init__(master)
>         self.grid()
>         self.create_widgets()
> 
>     def create_widgets(self):
>         list_chair=[(0, 0, '01'), (0, 1, '02'),
>                   (0, 3, '03'), (0, 4, '04'),
>                   (1, 0, '05')]
>         for row, column, name in list_chair:
>             command = partial(button_clicked, button)
>             button = tk.Button(self, color='green',
>                             command=command, text=name)
>             button.grid(row=row, column=column)
> 
> 
> 
> 
> root = tk.Tk()
> root.title("Test")
> root.geometry("200x200")
> app = Window(root)
> root.mainloop()
> 
> However, nothing happens when I run the program.

Nothing? That's bad. You should see something like

$ python3 tmp.py
Traceback (most recent call last):
  File "tmp.py", line 32, in <module>
    app = Window(root)
  File "tmp.py", line 14, in __init__
    self.create_widgets()
  File "tmp.py", line 21, in create_widgets
    command = partial(button_clicked, button)
UnboundLocalError: local variable 'button' referenced before assignment

Read the last line carefully. At that point in the program flow button is 
not yet defined. However, if you just swap the lines

button = tk.Button(self, color='green', command=command, text=name)
command = partial(button_clicked, button)

you'll quickly run into another problem: command is not yet defined when you 
create the button. Try it before you read on!

The only way out of the dilemma is to split the task into three steps:

- create the button
- create the callback
- link the callback to the button

button = tk.Button(self, color='green', text=name)
command = partial(button_clicked, button)
button["command"] = command

Now you're almost done. There's still one bug left, but it's an easy one and 
after reading the traceback carefully you should be able to fix it yourself.



More information about the Tutor mailing list