Как мне постоянно обновлять Tkinter, не замораживая все остальное? - PullRequest
0 голосов
/ 08 декабря 2018

Мне нужно отправить обновления в 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() также проблематичен, так как блокирует все остальные программы.Графический интерфейс всегда должен отвечать на обновления и не запрашивать их.

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