Мне нужно отправить обновления в tkinter из другого потока, которые должны быть обработаны немедленно.К сожалению, Tkinter зависает всякий раз, когда я пытаюсь использовать многопоточность.
Моя попытка:
Я прочитал несколько страниц с потоками Tkinter, но не нашел ничего, что хорошо работает, так как большинство из них пытаются создатьновый поток в button.click () , который здесь не помогает.
Я пытался не вызывать .mainloop () и вместо этого сам вызывать функции обновления,всякий раз, когда приходит обновление:
#GUI
def update(self, string):
self._interactor.config(text=string)
#interactor is a button
self._tk.update_idletasks()
self._tk.update()
Это работает нормально, пока я не использую цикл с sleep () в мастере для постоянного обновления текста.GUI и мастер заморожены во время сна ().Поэтому я попытался использовать поточный таймер , как описано здесь .
#MASTER
gui=gui_remote(self)
def changetext():
text=self.gettextsomewhere()
self._gui.update(text)
loop=RepeatedTimer(5, changetext)
Но это просто приводит к следующей ошибке, выдаваемой Tkinter:
RuntimeError: основной поток не в главном цикле
Трудно решить, как это решить.Можно ли вызвать класс GUI в главном потоке и при этом иметь надлежащий доступ к его функциям?
Как я дошел до этой точки:
Для моего проекта Мне нужна кнопка, который представляет несколько кнопок.
Каждые y (например, 1.5) секунды отображаемый текст должен обновляться до нового извне.
Кроме того, я хочу, чтобы графический интерфейс, контроллер и данные были разделены, (используя методы светокопии), так что последующие настройки для каждого из них будут проще.
Я уже заставил его работать, используя функцию TK's .after () , но мне пришлось использоватьGUI и управляющие функции тесно связаны друг с другом.
My Plan
Есть класс GUI, который можно обновлять из другого объекта с помощью простых общедоступных функций.Другой объект (мастер) должен иметь возможность создавать объект графического интерфейса и вызывать функции обновления графического интерфейса с новыми данными каждые y секунд.Когда кнопка GUI нажата, просто вызывайте определенный метод у мастера каждый раз:
#GUI example
from tkinter import Tk, Button, Frame, Label
class gui_sample:
def __init__(self, master):
"""This is the very simple GUI"""
self._master=master
self._tk=Tk()
self._interactor= Button(self._tk, text="Apfelsaft", command=self._click)
self._interactor.pack()
self._tk.mainloop()
def update(self, string):
"""Handle interactor update"""
self._interactor.config(text=string)
def _click(self):
self._master.click()
#MASTER
from gui_module import *
class Controller:
def __init__(self):
self._gui=gui_sample(self)
self._run()
def _run(self):
#call this every 5 seconds
new_text=self.gettextfromsomewhere()
self._gui.update(new_text)
def click():
#do something
pass
#this code is just a blueprint it probably does nothing
Моя проблема:
Я не хочу, чтобы мастер использовал функции TK, так как я мог бы переключитьсяпозже к другому модулю пользовательского интерфейса и сохранить функциональность мастера.Мастер будет постоянно переключаться между тем, что отображается дальше, и должен быть доступен одновременно.Использование циклов с sleep()
не очень хорошая идея, так как они блокируют как мастер, так и графический интерфейс.Вызов .mainloop()
также проблематичен, так как блокирует все остальные программы.Графический интерфейс всегда должен отвечать на обновления и не запрашивать их.