[Tutor] Tkinter class question

Peter Otten __peter__ at web.de
Sat Apr 8 03:12:17 EDT 2017


Phil wrote:

> I've progressed a little further but I'm now having a problem knowing when
> to use the "self" reference. In the following code, the function "ckeck"
> is called without the need to press the "check" button. This didn't occur
> before I sprinkled "selfs" into the code and added "array" to the "ckeck"
> function. I found that I needed "self" to point "array" to my list array
> "e" and I think that is where the fault is.
> 
> from tkinter import *
> 
> class TestGUI:
>     def __init__(self, master):
<...>

>         self.check_button = Button(master, text="Check",
>         command=self.check(self.e))

Think hard about what the expression

command=self.check(self.e)

does. Spoiler:

The check() method is invoked, and the result is passed as the command 
argument. But what is that result?

>     def check(self, array):
>         print("checked")
>         array[2][2].insert(0, "4")

No explicit return means the return value is None. Your above code is 
equivalent to

# print "checked" and insert "4"
self.check(self.e)
# create a button with no command
self.check_button = Button(master, text="Check", command=None)

To set a command you must define a function or method that takes no 
arguments:

class TestGUI:
    def check_2_2(self):
        print("checked"
        self.e[2][2].insert(0, "4")

    def __init__(self, master):
        ...
        self.check_button = Button(
            master,
            text="Check",
            command=self.check_2_2  # note there's no () -- the bound method
                                    # is not invoked
        )
        ...


> root = Tk()
> my_gui = TestGUI(root)
> root.mainloop()

If there are a lot of similar commands the command is often constructed by 
wrapping a method in a lambda with default arguments. Simple example:

import tkinter as tk

class TestGUI:
    def __init__(self, master):
        for i in range(5):
            button = tk.Button(
                master, 
                text="Button {}".format(i),
                command=lambda n=i: self.button_pressed(n)
            )
            button.grid(row=i, column=0)

    def button_pressed(self, n):
        print("You pressed button {}".format(n))

root = tk.Tk()
test = TestGUI(root)
root.mainloop()

There's also functools.partial() which can be used to the same effect

command=functools.partial(self.button_pressed, i)



More information about the Tutor mailing list