-2

I am writing a program using tkinter, but I do not understand how it works. Normally, code is executed top-down, but with tkinter it obviously does not.

For example, I have bound a function to the left mouse button, and this function is executed every time I click the button. But how is the other code around that treated? My problem is that I in the start of my program initialize a variable that is used as an argument in the bound function, and then it is changed in the function and returned. But every time the function is called, the variable seems to be reset to its initial value.

Does anyone know why this is?

I have it written like this:

var = "black"
var = c.bind("<Button-1>", lambda event: func(event, arg=var))

The function "func" changes var and returns it, but the next time I press the button the variable is always "black".

Thanks in advance!

David Hasselberg
  • 171
  • 1
  • 2
  • 13
  • You don't call functions like that in tkinter bindings. –  Mar 11 '16 at 11:12
  • How should you do it? Got it from here: http://stackoverflow.com/questions/33276717/passing-argument-to-bind-function-in-python?lq=1 – David Hasselberg Mar 11 '16 at 11:24
  • Never mind, also saw a mistake. Anyway, fixed and problem remains. – David Hasselberg Mar 11 '16 at 11:32
  • 1
    You are not assigning the returned value to anything. In your code `var` assigned to returned value of `bind()` not `func()` and if I'm not mistaken, you can not do what you are trying to achieve like that. You need to change `var` inside of `func` using classes or globals. – Lafexlos Mar 11 '16 at 12:59
  • Thanks a lot, looked up how to use classes with tkinter and it works now! – David Hasselberg Mar 11 '16 at 15:16

1 Answers1

0

Tkinter does indeed run top down. What makes tkinter different is what happens when it gets to the bottom.

Typically, the last executable statement in a tkinter program is a call to the mainloop method of the root window. Roughtly speaking, tkinter programs look like this:

# top of the program logic
root = tkinter.Tk()
...
def some_function(): ...
...
some_widget.bind("<1>", some_function)
...
# bottom of the program logic
root.mainloop()

mainloop is just a relatively simple infinite loop. You can think of it as having the following structure:

while the_window_has_not_been_destroyed():
    event = wait_for_next_event()
    process_event(event)

The program is in a constant state of waiting. It waits for an event such as a button click or key click, and then processes that event. Conceptually, it processes the event by scanning a table to find if that event has been associated with the widget that caught the event. If it finds a match, it runs the command that is bound to that widget+event combination.

When you set up a binding or associate a command with a button, you are adding something to that table. You are telling tkinter "if event X happens on widget Y, run function Z".

You can't use a return result because it's not your code that is calling this function. The code that calls the function is mainloop, and it doesn't care what the function returns. Anything that gets returned is simply ignored.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685