我需要根据某些条件停止/启动一个线程。我可以使用一个标志启动它然后停止它,但是当我再次尝试启动它时,我得到RuntimeError: threads can only be started once
例如,在以下代码中,用户按下转义键以启动或停止标签闪烁。第一次调用开始,第二次调用停止,但第三次调用我得到运行时错误。
from tkinter import *
import threading
import time
class App:
def __init__(self, master):
self.label = Label(text="TEXT?", font=('Helvetica', 30))
self.label.pack()
self.labelFlash = False
self.t = threading.Thread(target=self.flash)
root.bind("<Escape>", self.flashEvent)
def flashEvent(self, event):
if self.labelFlash == False:
self.labelFlash = True
self.t.start()
elif self.labelFlash == True:
self.labelFlash = False
print(self.labelFlash)
def flash(self):
while self.labelFlash == True:
self.label.config(bg='red')
root.update()
time.sleep(.5)
self.label.config(bg='green')
root.update()
time.sleep(.5)
root = Tk()
app = App(root)
root.mainloop()
如何在不收到此错误的情况下重新启动线程?谢谢。
答案 0 :(得分:0)
您可以使用threading.Event
对象来控制线程何时回调到gui。但是在事件循环线程之外调用gui是非法的,最终会导致崩溃。而是使用after()
方法在循环中安排定时事件。此事件可以安全地更改背景颜色,可以取消暂停操作。
from tkinter import *
import threading
import time
class App:
def __init__(self, master):
self.master = master
self.flash_colors = ['red', 'green']
self.cur_color = 0
self.flash_timer_id = None
self.label = Label(text="TEXT?", font=('Helvetica', 30))
self.label.pack()
root.bind("<Escape>", self.flashEvent)
def flashEvent(self, event):
if self.flash_timer_id is None:
# start flashing
self.flash()
else:
# stop flashing
self.master.after_cancel(self.flash_timer_id)
self.flash_timer_id = None
def flash(self):
self.label.config(bg=self.flash_colors[
self.cur_color%len(self.flash_colors)])
self.cur_color += 1
root.update()
# (delay in mS)
self.flash_timer_id = self.master.after(500, self.flash)
root = Tk()
app = App(root)
root.mainloop()