Как легко избежать замерзания Tkinter?
Я разработал простое приложение на Python, а потом решил добавить простой графический интерфейс с использованием Tkinter.
Проблема в том, что пока основная функция выполняет свои функции, окно зависает.
Я знаю, что это общая проблема, и я уже читал, что я должен использовать многопоточность (очень сложная, потому что функция также обновляет графический интерфейс) или разделять мой код на разные функции, каждая из которых работает в течение некоторого времени. Во всяком случае, я не хочу менять свой код для такого глупого приложения.
У меня вопрос: возможно ли, что нет простого способа обновлять окно Tkinter каждую секунду? Я просто хочу применить правило KISS!
Ниже приведу пример псевдокода, который я пытался, но не работал:
class Gui:
[...]#costructor and other stuff
def refresh(self):
self.root.update()
self.root.after(1000,self.refresh)
def start(self):
self.refresh()
doingALotOfStuff()
#outside
GUI = Gui(Tk())
GUI.mainloop()
Он просто выполнит обновление только один раз, и я не могу понять, почему.
Большое спасибо за вашу помощь.
4 ответа
Ткинтер находится в mainloop
, Что в основном означает, что оно постоянно обновляет окно, ждет нажатия кнопок, набираемых слов, выполнения обратных вызовов и т. Д. Когда вы запускаете некоторый код в том же потоке, который mainloop
включен, то больше ничего не будет выполнять на mainloop
пока этот раздел кода не будет сделан. Очень простой обходной путь - создание длинного процесса в отдельном потоке. Это все еще будет в состоянии общаться с Tkinter и обновлять его GUI (по большей части).
Вот простой пример, который радикально не изменяет ваш код psuedo:
import threading
class Gui:
[...]#costructor and other stuff
def refresh(self):
self.root.update()
self.root.after(1000,self.refresh)
def start(self):
self.refresh()
threading.Thread(target=doingALotOfStuff).start()
#outside
GUI = Gui(Tk())
GUI.mainloop()
Этот ответ входит в некоторые детали mainloop
и как это блокирует ваш код.
Вот еще один подход, который заключается в запуске GUI в его собственном потоке и последующем запуске другого кода.
Проблему «не отвечает» можно избежать, используя многопоточность в Python с помощью модуля потока.
Если вы определили какую-либо функцию, скажем, из-за которой окно Tkinter зависает, тогда заставьте другую функцию запускаться в фоновом режиме, как показано ниже:
import threading def combine(): ... def start_combine_in_bg(): threading.Thread(target=combine).start()
Теперь вместо звонка
Посмотрите ссылку: stackoverflow - избегайте зависания окна tkinter с использованием однострочного многопоточного кода
Вот как мне удалось обойти эту проблему (возможно, она довольно грязная, я не знаю):
Всякий раз, когда я обновляю свой
tkinter
окно через
doingALotOfStuff()
функция, я вызываю
myTk.update()
.
Для меня это помогает избежать замерзания.
Лучшее, что вы можете сделать для решения этой проблемы с зависанием, - это использовать многопоточность. Самый простой способ сделать это я опубликовал в своем ответе ранее здесь:окно Tkinter говорит (не отвечает), но код работает