Python:如何重新启动由flags停止的线程

时间:2018-05-20 19:56:19

标签: tkinter python-3.6 python-multithreading

我需要根据某些条件停止/启动一个线程。我可以使用一个标志启动它然后停止它,但是当我再次尝试启动它时,我得到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()

如何在不收到此错误的情况下重新启动线程?谢谢。

1 个答案:

答案 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()