我想在按下停止按钮后立即退出循环。但是使用这段代码,我只能在执行当前迭代和下一次迭代后才能出现。
这对我的应用来说非常重要,因为iam会将其用于自动化仪器,在按下停止按钮后必须立即停止操作。
# -*- coding: utf-8 -*-
"""
Created on Sun Jun 17 17:01:12 2018
@author: Lachu
"""
import time
from tkinter import *
from tkinter import ttk
root=Tk()
def start():
global stop_button_state
for i in range(1,20):
if (stop_button_state==True):
break
else:
print('Iteration started')
print('Iteration number: ', i)
root.update()
time.sleep(10)
print('Iteration completed \n')
def stop_fun():
global stop_button_state
stop_button_state=True
start=ttk.Button(root, text="Start", command=start).grid(row=0,column=0,padx=10,pady=10)
p=ttk.Button(root, text="Stop", command=stop_fun).grid(row=1,column=0)
stop_button_state=False
root.mainloop()
答案 0 :(得分:2)
将time.sleep
与GUI程序一起使用通常不是一个好主意,因为它会将所有置于睡眠状态,因此GUI无法自行更新或响应参加活动。此外,当您想要中断sleep
时,它会变得混乱。
我已调整您的代码以使用threading
模块中的Timer
。我们可以立即轻松中断此Timer
,并且它不会阻止GUI。
为了完成这项工作,我将您的计数for
循环移动到了生成器中。
如果在计数过程中按下“开始”按钮,它将告诉您它已在计数中。当计数周期结束时,无论是通过按停止,还是通过到达数字的末尾,您可以再次按开始以开始新的计数。
import tkinter as tk
from tkinter import ttk
from threading import Timer
root = tk.Tk()
delay = 2.0
my_timer = None
# Count up to `hi`, one number at a time
def counter_gen(hi):
for i in range(1, hi):
print('Iteration started')
print('Iteration number: ', i)
yield
print('Iteration completed\n')
# Sleep loop using a threading Timer
# The next `counter` step is performed, then we sleep for `delay`
# When we wake up, we call `sleeper` to repeat the cycle
def sleeper(counter):
global my_timer
try:
next(counter)
except StopIteration:
print('Finished\n')
my_timer = None
return
my_timer = Timer(delay, sleeper, (counter,))
my_timer.start()
def start_fun():
if my_timer is None:
counter = counter_gen(10)
sleeper(counter)
else:
print('Already counting')
def stop_fun():
global my_timer
if my_timer is not None:
my_timer.cancel()
print('Stopped\n')
my_timer = None
ttk.Button(root, text="Start", command=start_fun).grid(row=0, column=0, padx=10, pady=10)
ttk.Button(root, text="Stop", command=stop_fun).grid(row=1,column=0)
root.mainloop()
答案 1 :(得分:1)
使用print()
比使用线程更好:
在任何事件中,正如其他人指出的那样,在GUI中使用root.after
是一个坏主意。
您也不应该将您的按钮命名为与您的功能相同。
调用time.sleep
,这里也没有必要。
root.update
答案 2 :(得分:-1)
如果不使用单独的线程,您可以始终遍历sleep命令,这将使代码更具响应性 例如这将减少您在单击停止和循环退出到1/10秒之间的等待,同时在循环之间保持10秒的间隙。
# -*- coding: utf-8 -*-
"""
Created on Sun Jun 17 17:01:12 2018
@author: Lachu
"""
import time
from tkinter import *
from tkinter import ttk
root=Tk()
stop_button_state=False
def start():
global stop_button_state
for i in range(1,20):
if (stop_button_state==True):
break
print('Iteration started')
print('Iteration number: ', i)
for i in range(100):
root.update()
time.sleep(0.1)
if (stop_button_state==True):
break
print('Iteration completed \n')
def stop_fun():
global stop_button_state
stop_button_state=True
ttk.Button(root, text="Start", command=start).grid(row=0,column=0,padx=10,pady=10)
ttk.Button(root, text="Stop", command=stop_fun).grid(row=1,column=0)
root.mainloop()