Обновление фоновой метки на основе событий Tkinter

Моя программа выполняет сложные вычисления, которые длятся около 30 минут. Я хотел бы быть в курсе значений некоторых переменных в графическом интерфейсе Tkinter с идеально определенными переменными, связанными с определенными метками, чтобы они автоматически обновлялись всякий раз, когда они изменяют свои значения. Хотя я понимаю, что могу создать 2 потока (один для основной программы и один для TKinter, который вызывает себя каждую секунду или около того), мне интересно, есть ли более элегантный способ справиться с этим. Любые предложения приветствуются.

В приведенном ниже примере показано, как это могло бы выглядеть, но пример не работает.

import Tkinter as tk
import time

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.counter = tk.Label(self, text="")
        self.counter.pack()

        # start the clock "ticking"
        self.mainLoop()

    def mainLoop(self):
        for i in range (10000):
            j=i^2
            self.counter.configure(text=str(j))
            time.sleep(0.1)

if __name__== "__main__":
    app = SampleApp()
    app.mainloop()

Однако это работает, когда mainLoop заменен на это:

def mainLoop(self):
    now = time.strftime("%H:%M:%S" , time.gmtime())
    self.counter.configure(text=now)
    # call this function again in one second
    self.after(1000, self.mainLoop)

Мои вопросы:

  1. Почему это работает с «self.after», но не с циклом for
  2. Есть ли более элегантный способ обновления меток, управляемый событиями (не на основе кнопки, а на вычислении, которое изменяет определенные переменные)

person Nickpick    schedule 18.08.2015    source источник
comment
Вы пытались найти в Google такие термины, как tkinter python после сна?   -  person TigerhawkT3    schedule 18.08.2015


Ответы (1)


Чтобы ответить на первый вопрос -

Почему это работает с «self.after», но не с циклом for

Метод __init__() класса вызывается при создании объекта этого класса. Теперь в вашем случае класс создается в строке -

app = SampleApp()

А в вашем __init__() вы называете - self.mainLoop() .

В вашем случае цикла for все это выполняется в основном потоке. И поэтому он не вернется из self.mainLoop(), пока не завершится, поскольку вы не запускаете self.mainLoop() как отдельный поток, вы делаете это в том же потоке. Следовательно, элемент управления достигнет строки root.mainloop() только после того, как self.mainLoop()` завершится и вернет элемент управления обратно.


В случае использования метода after() он ведет себя примерно так, как будто регистрирует событие, которое должно быть запущено через некоторое время, и немедленно возвращается, он не ждет ни столько времени, ни возврата функции. Следовательно, элемент управления немедленно возвращается и вызывает root.mainloop() для отображения графического интерфейса.

person Anand S Kumar    schedule 18.08.2015