Python: обновить виджет холста tkinter из событий потоков - PullRequest
0 голосов
/ 16 октября 2018

Я пытаюсь сделать индикатор состояния на моем графическом интерфейсе tkinter.На данный момент я просто хочу повернуть его с зеленого на красный, чтобы показать, что сценарий не заморожен.Все ошибки отслеживания Python, которые я получаю, указывают на __libraries, которые я не понимаю.Я чувствую, что это должно быть проблемой с пространством имен, но я вырываю свои волосы, пытаясь положить на них свой палец.

Метод eventCheck () отлично работал при создании метки, которая переключалась между 0 и 1, прежде чем я создал объект canvas и попытался передать в него символ c.Там так мало информации о том, что я пытаюсь сделать, может быть, есть лучший способ?

Вот сокращенная версия моего сценария:

import tkinter as tk
from tkinter import Canvas
import time
import threading

class myGUI(tk.Frame):

    def __init__(self, master, event):
        self.master = master
        self.event = event
        super().__init__(master)

        self.label = tk.Label(self, text="")
        self.label.grid()
        self.after(1, self.eventCheck)

        c = tk.Canvas(self, bg='white', width=80, height=80)
        c.grid()
        self.eventCheck(c)

    def redCircle(self, c):
        c.create_oval(20, 20, 80, 80, width=0, fill='red')
        print("redCircle Called")

    def greenCircle(self,c):
        c.create_oval(20, 20, 80, 80, width=0, fill='green')
        print("greenCircle Called")

    def eventCheck(self, c):
        self.label['text'] = self.event.is_set()
        if self.label['text'] == 0:
            self.redCircle(c)
        else:
            self.greenCircle(c)
        self.after(2000, self.eventCheck(c))

def timingLoop(event):
    while True:
        event.set()
        time.sleep(2)
        event.clear()
        time.sleep(2)

def main():
    root = tk.Tk()
    root.title("myFirst GUI")
    event = threading.Event()
    t=threading.Thread(target=timingLoop, args=(event,))
    t.daemon = True
    t.start()
    app = myGUI(root, event)
    root.mainloop()

if __name__=="__main__":
    main()

1 Ответ

0 голосов
/ 16 октября 2018

Я обнаружил две основные проблемы с вашим кодом.Во-первых, это не делает то, что, как вы думаете, следует:

def eventCheck(self, c):
        # ...
        self.after(2000, self.eventCheck(c))

Поскольку вы передали результат вызова self.eventCheck(c) в after() вместо метода self.eventCheck, это бесконечно.рекурсия, которая происходит немедленно.

Вторая проблема заключается в том, что если вы закомментируете все ваши хронометраж и события, ваш интерфейс на самом деле никогда не появится, поэтому там никогда ничего не будет видно.Я сжал (упростил) ваш пример сценария еще дальше до сценария, который в основном работает:

import tkinter as tk
import threading
import time

class myGUI:

    def __init__(self, master, event):
        self.master = master
        self.event = event

        self.label = tk.Label(master, text="")
        self.label.pack()

        self.canvas = tk.Canvas(master, bg='white', width=80, height=80)
        self.canvas.pack()

        self.eventCheck()

    def redCircle(self):
        self.canvas.create_oval(20, 20, 80, 80, width=0, fill='red')
        print("redCircle Called")

    def greenCircle(self):
        self.canvas.create_oval(20, 20, 80, 80, width=0, fill='green')
        print("greenCircle Called")

    def eventCheck(self):
        flag = self.event.is_set()

        self.label['text'] = flag

        if flag:
            self.greenCircle()
        else:
            self.redCircle()

        self.master.after(2000, self.eventCheck)

def timingLoop(event):
    while True:
        event.set()
        time.sleep(2)
        event.clear()
        time.sleep(2)

def main():
    root = tk.Tk()
    root.title("myFirst GUI")

    event = threading.Event()
    t = threading.Thread(target=timingLoop, args=(event,))
    t.daemon = True
    t.start()

    app = myGUI(root, event)
    root.mainloop()

if __name__ == "__main__":
    main()

enter image description here

Теперь вы сможете добавить обратноваш Frame суперкласс.Обязательно добавьте фрейм myGUI к корневому объекту.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...