Я пытаюсь реализовать простую, легковесную систему для записи событий Qt GUI и воспроизведения их из сценария. Я думал, что было бы довольно просто использовать магию системы событий Qt, но я столкнулся с проблемой, которую не понимаю.
Вот краткое изложение того, что я делаю:
ЗАПИСЬ:
я использую 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) нить. (Я не могу использовать поток GUI, потому что я хочу продолжать посылать скриптовые события в приложение, даже если «главный» цикл событий блокируется, пока работает модальный диалог событий.)
Важные вещи происходят в моем post_event()
функция, которая должна делать две вещи:
QApplication.postEvent(obj, recorded_event)
obj
работает в.QApplication.processEvents()
После завершения второй части я ожидаю, что все эффекты первой части (записанного события) завершены, так как специальное мероприятие было поставлено в очередь после записанное событие.
Вся система в основном Кажется, что он отлично работает для событий мыши, ключевых событий и т. д. Но у меня проблема с QAction
обработчики, когда я пытаюсь воспроизвести события для моего основного QMenuBar
,
Неважно, что я пытаюсь, кажется, что Я не могу принудительно заблокировать поток воспроизведения для завершения всех QAction.triggered
обработчики этот результат от нажатия на мой QMenu
Предметы. Насколько я могу сказать, QApplication.processEvents()
возвращается до QAction
обработчик завершен.
Есть что-то особенное в QMenu
виджеты или QAction
сигналы, которые нарушают нормальные правила QApplication.postEvent()
и / или QApplication.processEvents()
? Мне нужен способ заблокировать для завершения моего QMenu
«s QAction
обработчики.
spontaneous()
события, и я также отфильтровываю несколько других типов (например, Paint
события и обычные движения мыши).
[**] Это важно, потому что следующее событие в скрипте может относиться к виджету, который был созданный по предыдущему событию.
Я думаю, что ваша проблема может быть лучше всего решена с помощью QFuture и QFutureWatcher (то есть, если вы используете пространство имен QtConcurrent для потоков, а не QThreads). По сути, система обработки событий Qt НЕ обязательно обрабатывает события в порядке их публикации. Если вам нужно заблокировать, пока не будет выполнено определенное действие, и вы выполняете это действие в отдельном потоке, вы можете использовать объект QFuture, возвращенный QtConcurrent :: run () с QFutureWatcher, чтобы блокировать, пока этот конкретный поток не завершит свою обработку ,
Что-то еще нужно учитывать, как вы обрабатываете события. Когда вы используете QApplication.postEvent (), создаваемое вами событие добавляется в очередь событий получателя для последующей обработки. За кулисами Qt может переупорядочить и сжать эти события, чтобы сэкономить время процессора. Я подозреваю, что это больше ваша проблема.
В вашей функции, которая обрабатывает воспроизведение, рассмотрите возможность использования QCoreApplication :: processEvents (), которая не вернется, пока все события не завершат обработку. Документация для QCoreApplication Вот.
Виджеты QMenu и сигналы QAction являются особым случаем. QMenu имеет функцию exec (), обычно используемую для всплывающих окон. Я подозреваю (но не знаю наверняка), что QMenuBar будет использовать этот механизм, когда он открывает обычное выпадающее меню. Документы не совсем ясны по этому поводу, но меню во многом похожи на диалоговые окна в том, что они блокируют все другие действия пользователя — как бы Qt делал это, кроме как предоставляя меню свой собственный цикл обработки событий? Я не могу заполнить все пробелы из информации в вашем посте, но я не вижу, как ваша ветка воспроизведения справится с новым циклом событий.