управление элементами пользовательского интерфейса в wxPython с использованием потоков

Я пишу простую игру, используя Python / wxWidgets.

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

Архитектура, которой я располагаю до сих пор, заключается в том, что приложение запускается и запускает второй поток, который запускает функцию под названием «gameLogic». Основной поток затем переходит в основной цикл приложения.

Поток gameLogic выполняется последовательно и требует контроля над пользовательским интерфейсом. Например, необходимо открыть новое диалоговое окно с основным фреймом в качестве родителя. Тем не менее, я обнаружил, что это приводит к сбоям (достаточно плохо, чтобы всплывать окно сбоя отчета в OS X).

Я просматривал и собирал то, что мне нужно для рефакторинга для использования событий, но я не уверен, как это сделать, это создать свои собственные события. Я мог бы, чтобы поток gameLogic поднимет событие в главном окне, которое затем откроет диалоговое окно ввода и дождитесь ввода (модально), а затем вернет эти данные обратно в поток gameLogic. Поток gameLogic может блокироваться во время ожидания, потому что поток пользовательского интерфейса является отдельным.

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

Я видел всевозможные идеи для реализации этого, но не смог найти хороший пример того, как создать настраиваемое событие в моем объекте wxFrame и вызвать его из другого потока, а также иметь блок логической строки и дождитесь возврата ввода, а затем, как получить этот вход обратно в gameThread.

Совет очень оценили!

One Solution collect form web for “управление элементами пользовательского интерфейса в wxPython с использованием потоков”

Во-первых, сложная часть:

Я видел всевозможные идеи для реализации этого, но не смог найти хороший пример того, как создать настраиваемое событие в моем объекте wxFrame и вызвать его из другого потока

Вот пример этого права на wxPyWiki . Вы также можете посмотреть ссылку на Работу с wxPython в отдельном потоке .

Тем не менее, я думаю, что сообщение в блоге wxPython и Threads от The Mouse Vs. Python объясняет трудную часть лучше всего. И это также показывает вам более простой способ сделать это (используя CallAfter и Publisher вместо публикации пользовательских событий), но давайте придерживаться того, о чем вы просили.

Единственное, что ему не хватает:

… а также иметь блок логического потока и ждать, пока не вернется вход, а затем, как получить этот вход обратно в gameThread.

Но в этом нет ничего странного. Единственная причина, по которой отправка информации в wx (или любой цикл событий) сложна, заключается в том, что цикл события не может блокироваться. Ваш логический поток может блокировать, а на самом деле должен . Таким образом, любой нормальный механизм синхронизации потоков просто отлично.

Итак, у вас есть один поток, который хочет заблокировать навсегда до тех пор, пока значение не будет готово, и еще один поток, который хочет отправить это значение без блокировки. Вы можете сделать это довольно легко с Condition или Queue . Последнее, вероятно, слишком велико, но это более гибко, так что давайте сделаем это, просто для удовольствия.

Я возьму пример из блога Mouse и сделаю так, чтобы каждый раз, когда фоновый поток EVT_RESULT событие EVT_RESULT , он блокируется до тех пор, пока это событие не будет обработано, возвращая строку, которая может … записать или что-то еще, я думаю, это не очень полезно, но я хотел показать ему что-то .

 from queue import Queue # ... class TestThread(Thread): # ... def run(self): for i in range(6): # ... wx.PostEvent(self.wxObject, ResultEvent(amtOfTime) result_from_gui = self.wxObject.q.get(True, None) # ... class MyForm(wx.Frame): # ... def __init__(self): # ... self.q = Queue() # ... def updateDisplay(self, msg): # ... t = msg.data if isinstance(t, int): text = "Time since thread started: %s seconds" % t else: text = "%s" % t self.btn.Enable() self.displayLbl.SetLabel(text) self.q.put(text) 

В этом примере поток GUI выполняет self.q.put(text) в конце updateDisplay . Там нет волшебной причины, по которой она должна быть там, а затем – пока это происходит (и ровно один раз), логический поток будет блокироваться до тех пор, пока это не произойдет. Например, метод updateDisplay может создать новую кнопку и отправить self.q.put (и удалить кнопку), когда пользователь нажмет на нее.

  • Как я могу установить пробел в Vertical BoxSizer?
  • Проверка данных в wxPython
  • wx.TaskBarIcon на Ubuntu 11.04
  • Каков наилучший вид графического виджета в режиме реального времени для wxPython?
  • wxPython: элементы в BoxSizer не расширяются горизонтально, только вертикально
  • Как добавить контур границы к виджету?
  • Получить значение слайдера wxpython под щелчком мыши
  • wxPython / ReportLab: как создать и открыть файл .pdf при нажатии кнопки
  • Сортировка по столбцам в wxpython?
  • Установка фона выбора в ListCtrl
  • Как сделать wx.TextEntryDialog более крупным и изменяемым по размеру
  • Python - лучший язык программирования в мире.