Как обновить элементы Kivy из потока?

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

 class View(BoxLayout): def __init__(self, **kwargs): super(View, self).__init__(**kwargs) self.btn = Button(text='Default') # Bind button press method self.btn.bind(on_press=self.message) self.add_widget(self.btn) def message(self, message): self.btn.text = 'Meow' self.add_widget(Button(text='Meow')) print(str(message)) 

Функция сообщения действительно вызывается и выводится, но интерфейс не обновляется. Однако, когда я нажимаю кнопку, он обновляет интерфейс, а также печатает.

Я изучил использование StringProperty чтобы изменить текст кнопки, но тоже не удалось. Точно так же, как примечание, в случае, если то, что я делаю, совершенно неосуществимо, я пытаюсь позже нарисовать весь интерфейс, состоящий из кнопок width * height в виде доски.

Любой вход очень ценится, это сводит меня с ума.


EDIT 1 * Я следил за несколькими комментариями и пробовал несколько вещей. Я добавил класс Clock и планирую метод update() из View . Метод обновления просто изменяет текст нескольких элементов. Я заметил, что это работает, когда я планирую его, как показано ниже:

 def update(self, *args, **kwargs): self.btn.text = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase) for i in range(32)) def message(self, message): try: print(message) self.text = 'sending' except Exception as e: print(e) 

Теперь поток просто присваивает свойство text, как показано в message() . Периодически запускаемые методы update() работают, присваивая случайный текст. Теперь проблема в том, что он не может установить текст. Это не работает:

 def update(self, *args, **kwargs): self.btn.text = self.text 

Должно быть, я ошибаюсь в другом месте, любые предложения?


EDIT 2 * Ошибка, которую я пытаюсь отлаживать, здесь .

One Solution collect form web for “Как обновить элементы Kivy из потока?”

Поскольку вы не публикуете полный рабочий пример, я могу только догадываться о том, что вы делаете. Кажется, у вас есть событие (входящее сообщение) в потоке, и вы хотите отобразить некоторый текст, когда это происходит. Вам нужно «нажимать» обновления пользовательского интерфейса на основной поток, но вам не нужно делать периодические обновления с помощью Clock , вы можете просто планировать одноразовые звонки с Clock.schedule_once .

 from functools import partial def update(self, text, *a): self.btn.text = text def message(self, message): Clock.schedule_once(partial(self.update, message), 0) 

Как упоминалось выше, вы можете сделать это «push to main thread» автоматически с @mainthread декоратора @mainthread :

 @mainthread def update(self, text): self.btn.text = text def message(self, message): update(message) 

Таким образом, всякий раз, когда вы вызываете update он будет выполняться в основном потоке.

  • Регулировка экспозиции (яркость / контрастность) на основе гистограммы с использованием Python
  • Kivy - базовое приложение имеет странное выравнивание
  • Два киви изображения в BoxLayout
  • Как вернуть виджет внутри макета в Kivy?
  • Лучший графический интерфейс для python?
  • Добавление полосы прокрутки в Boxlayout в Киви
  • почему щелчок правой кнопкой мыши создает оранжевую точку в центре круга?
  • python kivy с ошибками приложения plyer на Android (камера)
  • Python - лучший язык программирования в мире.