Я пытаюсь реализовать простую, легкую систему для записи событий Qt GUI и воспроизведения их из сценария. Я думал, что это будет довольно просто, используя магию системы событий Qt, но я столкнулся с проблемой, которую я не понимаю.Запись и воспроизведение событий Qt GUI
Вот краткий обзор того, что я делаю:
ЗАПИСЬ:
Я использую QApplication.instance().eventFilter()
, чтобы захватить все события GUI Я заинтересован в * и сохранить их в скрипт Python, в котором каждый шаг выглядит примерно так:
obj = get_named_object('MainWindow.my_menubar')
recorded_event = QMouseEvent(2, PyQt4.QtCore.QPoint(45, 8), 1, Qt.MouseButtons(0x1), Qt.KeyboardModifiers(0x0))
post_event(obj, recorded_event)
ВОСПРОИЗВЕДЕНИЯ:
Я просто выполнить сценарий выше, работник (не-GUI) нить. (Я не могу использовать поток графического интерфейса, потому что я хочу продолжать отправлять сценарии в приложение, даже если «главный» eventloop заблокирован, пока работает модальный диалог eventloop.)
Важный материал происходит в моем post_event()
функция, которая должна сделать две вещи:
- Сначала вызовите
QApplication.postEvent(obj, recorded_event)
- Ожидать все события завершения обработки: **
- Post специальное событие к тому же eventloop, что
obj
запущен. - Когда специальное событие обрабатывается:
- Вызов
QApplication.processEvents()
- Установите флажок, который говорит воспроизведение нить это нормально продолжать
- Вызов
- Post специальное событие к тому же eventloop, что
После второй части завершена, я ожидаю, что все эффекты первой части (записанного события) завершили, так как специальное событие было поставлено в очередь af ter записанное событие.
Вся система в основном, кажется, работает просто отлично для событий мыши, ключевые события и т.д. Но у меня проблема с QAction
обработчиков при попытке воспроизвести события для моего основного QMenuBar
.
Независимо от того, что я стараюсь, она не кажется, что я не могу заставить мое воспроизведение нити заблокировать для завершения всех QAction.triggered
обработчиков, что в результате нажатия на моих QMenu
пунктах. Насколько я могу судить, QApplication.processEvents()
возвращает доQAction
обработчик завершен.
Есть ли что-то особенное QMenu
виджетов или QAction
сигналов, что нарушает нормальные правила QApplication.postEvent()
и/или QApplication.processEvents()
? Мне нужен способ блокировки для завершения моих обработчиков QMenu
QAction
.
[*] Не все события зарегистрированы. Я регистрирую только spontaneous()
событий, а также отфильтровываю несколько других типов (например, Paint
событий и обычных движений мыши).
[**] Это важно, потому что следующее событие в скрипте может ссылаться на виджет, который был создан предыдущим событием.
Я уже вызываю 'QApplication.processEvents()' во время воспроизведения (это не было ясно в моем вопросе, поэтому я отредактировал его). –
Кроме того, спасибо за отзыв о Qt Concurrent - я раньше не видел эту библиотеку. Тем не менее, я не думаю, что это помогает мне в этом случае. Если я что-то не упустил, Qt Concurrent не позволяет мне * выбрать *, какой поток выполнить мою работу. Мне нужно, чтобы мое «специальное» действие обрабатывалось в основном потоке gui. В настоящее время я достигаю этого с помощью сигнала, который находится в потоке GUI, который я «подключаю()» к использованию «Qt.QueuedConnection». И все же ... он не ведет себя так, как ожидаешь, когда участвует «QMenu». –
Ну, если вы делали эту обработку в отдельном потоке, QtConcurrent позволил бы вам выбрать «поток», чтобы запустить его. Так как вы делаете это в основном потоке, это не работает. Учитывая, что вы испытываете нестандартное поведение от QApplication, я подозреваю, что вы столкнулись с какой-то проблемой синхронизации с вашими потоками. Возможно, что действия QMenu не помещаются в очередь событий, когда вы думаете, что они есть. Мой лучший совет - попробовать отладить это, переместив работу post_event() в основной поток. Если это сработает, тогда вы узнаете, что у вас есть проблема синхронизации потоков. – gankoji