Hi I have a small python gui interface with two buttons, start(That starts a counter) and stop (that is suppose to stop the counter), the counter is an infinite loop since I do not want it to end unless the second button is clicked. The problem is the second button cannot be clicked while the function from the first one is still running. I read that I need to use threading and I have tried but I do not fully understand how I can do this. Please help.
from Tkinter import *
import threading
class Threader(threading.Thread):
def run(self):
for _ in range(10):
print threading.current_thread().getName()
def main(self):
import itertools
for i in itertools.count(1, 1):
print i
def other(self):
print "Other"
m = Threader(name="main")
o = Threader(name="other")
try:
'''From here on we are building the Gui'''
root = Tk()
'''Lets build the GUI'''
'''We need two frames to help sort shit, a left and a right vertical frame'''
leftFrame = Frame(root)
leftFrame.pack(side=LEFT)
rightFrame = Frame(root)
rightFrame.pack(side=RIGHT)
'''Widgets'''
'''Buttons'''
playButton = Button(leftFrame, text="Play", fg="blue", command=m.main)
stopButton = Button(rightFrame, text="Stop", fg="red", command=o.other)
playButton.pack(side=TOP)
stopButton.pack(side=BOTTOM)
root.mainloop()
except Exception, e:
print e
Here's a short example of using threading
. I took out your other
function and I don't know why your using itertools
here. I took that out as well and simply setup using a simple threading example.
A few things:
You setup using threading.Thread
as the base class for Threader
, but you never actually initialized the base class.
Whenever you use threading you generally want to define a run
method and then use start()
to start the thread. Calling start()
will call run
.
You need to use threading to prevent your GUI blocking, because tkinter is just one thread on a giant loop. So, whenever you have some long running process it blocks this thread until the current process is complete. That's why it's put in another thread. Python has something called the GIL, which prevent's true parallelization (I made up that word) since it only one thread can ever be used at a time. Instead, it uses time slicing, the GIL sort of "polls" between them to give the appearance of multiple tasks running concurrently. For true parallel processing you should use multiprocessing
.
In the below code I have used self.daemon = True
. Setting the thread to be a daemon will kill it when you exit the main program (In this case the Tk GUI)
from tkinter import *
import threading, time
class Threader(threading.Thread):
def __init__(self, *args, **kwargs):
threading.Thread.__init__(self, *args, **kwargs)
self.daemon = True
self.start()
def run(self):
while True:
print("Look a while true loop that doesn't block the GUI!")
print("Current Thread: %s" % self.name)
time.sleep(1)
if __name__ == '__main__':
root = Tk()
leftFrame = Frame(root)
leftFrame.pack(side=LEFT)
rightFrame = Frame(root)
rightFrame.pack(side=RIGHT)
playButton = Button(leftFrame, text="Play", fg="blue",
command= lambda: Threader(name='Play-Thread'))
stopButton = Button(rightFrame, text="Stop", fg="red",
command= lambda: Threader(name='Stop-Thread'))
playButton.pack(side=TOP)
stopButton.pack(side=BOTTOM)
root.mainloop()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With