[Tutor] Tkinter and threading
Peter Otten
__peter__ at web.de
Thu Jun 2 12:39:23 EDT 2016
Marco Soldavini wrote:
> Hello,
> probably this is a very naive question, but I've read some stuff on
> Tkinter and its infinite loop.
>
> Then about how can i bind actions to elements, for example buttons.
>
> What if I want to run another loop beside the graphical interface in
> the same python script?
I usually adapt http://effbot.org/zone/tkinter-threads.htm
> For example a state machine with a var state which can have some
> discrete string values (like RUNNING, STOPPED, PAUSED, ABORTED, IDLE)
> and a text element on the gui that reports that state.
>
> So a button cause a transition > the python loop (not the gui loop)
> detects the transition and changes the state var value > the gui
> refresh its value on screen.
>
> I wrote some code to try it without threading but it does not give the
> expected result as it seems the button update status action is already
> triggered. I am missing some basic point here
Indeed your problem has nothing to do with threads.
>
> from Tkinter import *
>
> state = "STOPPED"
>
> root = Tk()
>
> myContainer1 = Frame(root)
> myContainer1.pack()
> label1=Label(myContainer1, text=state, font = "Helvetica 16 bold italic")
> label1.pack()
>
> def change(new_state):
> label1.config(text=new_state)
>
> button1 = Button(myContainer1, text="START")
> button1.bind("<Button-1>", change("START"))
In the line above you invoke the change function and bind its result (None)
to the button1 widget's <Button-1> event. Instead you should pass a function
that will be invoked by Tkinter when the button is pressed:
def start(event):
change("START")
button1.bind("<Button-1>", start)
You can define simple functions inline, so
button1.bind("<Button-1>", lambda event: change("START"))
would also work. However, the usual way to bind actions to Button widgets is
to pass the callback function as the command argument to the constructor:
button = Button(container, command=your_func_that_takes_no_args)
With that approach your script will become
from Tkinter import *
def change(new_state):
label1.config(text=new_state)
def start():
change("RUNNING")
def stop():
change("STOPPED")
root = Tk()
myContainer1 = Frame(root)
myContainer1.pack()
label1 = Label(myContainer1, font="Helvetica 16 bold italic")
label1.pack()
stop()
button1 = Button(myContainer1, text="Start", command=start)
button1.pack()
button2 = Button(myContainer1, text="Stop", command=stop)
button2.pack()
root.mainloop()
More information about the Tutor
mailing list