Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python

Josh Keenan
Josh Keenan
19,529 Points

Tkinter Button problem

So what I'm doing is placing 35 buttons in a grid, each using a function called function (inventive right?).

In tkinter to make a button work you can't use parentheses when setting the command, otherwise it runs as soon as the program starts, I need to use them and obviously the code runs instantly.

Anyone know how to stop this?

    def function(self, text):
        print (text)

    def mock_fill(self, row, col, text):
        #temp = tkinter.Label(
         #   self.mainframe,
        #    bg='grey',
         #   text=text,
        #    fg='black',
          #  font=('Helvetica', 10)
        #)

        temp = tkinter.Button(
            self.mainframe,
            text=text,
            command=self.function(text)
        )

        temp.grid(
            row=row, column=col,
            sticky='ew',  # East West
            padx=10, pady=10
        )

Thanks :)

Chris Freeman
Chris Freeman
Treehouse Moderator 68,082 Points

Can I assume mock_fill isn't intended to be indented to be a method of function?

Josh Keenan
Josh Keenan
19,529 Points

Yes that is an indentation error when copying in to treehouse, my bad!

2 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,082 Points

Good. Because I plan to make function a method of mock_fill....

    def mock_fill(self, row, col, text):
        # temp = tkinter.Label(
        #    self.mainframe,
        #    bg='grey',
        #    text=text,
        #    fg='black',
        #    font=('Helvetica', 10)
        # )

        def function(self):  # <-- note drop of param 'text'
            print (text)  # 'text' becomes an encapsulated global for 'function'

        temp = tkinter.Button(
            self.mainframe,
            text=text,
            command=function  # <-- reference local function
        )

        temp.grid(
            row=row, column=col,
            sticky='ew',  # East West
            padx=10, pady=10
        )

To see this in practice:

$ python3
Python 3.4.0 (default, Jun 19 2015, 14:20:21) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class MockItAll():
...     def mock_fill(self, row, col, text):
...         def funct():
...             print(text)
...         setattr(self, "mock_{}_{}".format(row, col), funct)
... 
>>> mock_all = MockItAll()
# Create function as an attribute to call later
>>> mock_all.mock_fill(0, 0, "zero-zero")
>>> mock_all.mock_0_0
<function MockItAll.mock_fill.<locals>.funct at 0x7fa9d63af730>
# Call function
>>> mock_all.mock_0_0()
zero-zero
# Create 2nd function
>>> mock_all.mock_fill(0, 1, "zero-one")
>>> mock_all.mock_0_1
<function MockItAll.mock_fill.<locals>.funct at 0x7fa9d63af840>
# Call second function
>>> mock_all.mock_0_1()
zero-one
Josh Keenan
Josh Keenan
19,529 Points

I swear one day I will be as good as you! Thanks as always Chris! :)

Josh Keenan
Josh Keenan
19,529 Points

Had to drop the self from function in my IDE, weird huh? But it all works, thanks a lot!