Python: Как перезапустить поток, остановленный флагом - PullRequest
0 голосов
/ 20 мая 2018

Мне нужно остановить / запустить поток на основе определенных условий.Я могу использовать флаг, чтобы запустить его, а затем остановить его, но когда я пытаюсь запустить его снова, я получаю RuntimeError: threads can only be started once

. Например, в следующем коде пользователь нажимает клавишу escape для запуска или остановки.этикетка от перепрошивки.Первый вызов начинается, второй вызов останавливается, но третий вызов вызывает ошибку во время выполнения.

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 голосов
/ 20 мая 2018

Вы можете использовать объект threading.Event для контроля, когда поток перезванивает в графический интерфейс.Но вызов в графический интерфейс за пределами потока цикла событий недопустим и в конечном итоге приведет к сбою.Вместо этого используйте метод 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()
...