Reputation: 55
I'm new to Python and even more so to tkinter, and I decided to try to create a start and stop button for an infinite loop through Tkinter. Unfortunately, once I click start, it won't allow me to click stop. The start button remains indented, and I assume this is because the function it triggered is still running. How can I make this 2nd button stop the code?
import tkinter
def loop():
global stop
stop = False
while True:
if stop == True:
break
#The repeating code
def start():
loop()
def stop():
global stop
stop = True
window = tkinter.Tk()
window.title("Loop")
startButton = tkinter.Button(window, text = "Start", command = start)
stopButton = tkinter.Button(window, text = "Pause", command = stop)
startButton.pack()
Upvotes: 1
Views: 3073
Reputation: 133
Thank you! @Pythonista, It works for me stopping a for loop in the tkinter. But it is likely not an effective way to do that because the frame was stuck after I pressed the stop button as demonstrated below with part of script: `
def start_scan(self):
self.voltage_scan(
self.start.get(),
self.stop.get(),
self.step.get(),
self.delay.get()
)
def start_butt(self):
if self.poll:
self.start_scan()
def stop_butt(self):
self.poll = False
def voltage_scan(self, start, stop, step, delay):
def make_plot():
plt.scatter(mvol,mcurr)
plt.xlabel('Voltage / V', fontsize = 12)
plt.ylabel('Current / A', fontsize = 12)
plt.tight_layout()
if start < stop:
stop = stop + 1
plt.ion() # enable interactivity
fig = plt.figure(figsize = (5,3.5), dpi = 100)
ax = fig.add_subplot(111)
curr = 0
mvol = []
mcurr = []
for vol in range(start, stop, step):
if self.poll:
mvol.append(vol)
#time.sleep(1 / delay)
self.after(1000*delay) # 1 second delay
curr += 1
mcurr.append(curr)
#print(vol, curr)
drawnow(make_plot)
else:
break
`
There might be better way to do that. or at least there would be a way to refresh the frame without closing the program. bcz I have to restart the program after evrytime I press the stop button.
Upvotes: 0
Reputation: 11615
You're calling while True
. Long story short, Tk()
has it's own event loop. So, whenever you call some long running process it blocks this event loop and you can't do anything. You should probably use after
I avoided using global
here by just giving an attribute to window
.
e.g. -
import tkinter
def stop():
window.poll = False
def loop():
if window.poll:
print("Polling")
window.after(100, loop)
else:
print("Stopped long running process.")
window = tkinter.Tk()
window.poll = True
window.title("Loop")
startButton = tkinter.Button(window, text = "Start", command = loop)
stopButton = tkinter.Button(window, text = "Pause", command = stop)
startButton.pack()
stopButton.pack()
window.mainloop()
Upvotes: 2