События простоя wx и обновления пользовательского интерфейса в PyQt

StackOverflow https://stackoverflow.com/questions/624050

  •  05-07-2019
  •  | 
  •  

Вопрос

В wx (и wxPython) есть два события, которые мне не хватает в PyQt:

  • EVT_IDLE это отправляется в кадр.Его можно использовать для обновления различных виджетов в зависимости от состояния приложения.
  • EVT_UPDATE_UI это отправляется виджету, когда его нужно перерисовать и обновить, чтобы я мог вычислить его состояние в обработчике

Похоже, что в PyQt их нет, и в книге PyQt предлагается написать updateUi метод и вызвать его вручную.В итоге я даже вызывал его по таймеру раз в 0,1 секунды, чтобы избежать множества ручных вызовов из методов, которые могут обновить графический интерфейс.Я что-то пропустил?Есть ли лучший способ добиться этого?


Пример:У меня есть простое приложение с кнопкой «Пуск», которая инициирует некоторую обработку.Кнопка «Пуск» должна быть включена только в том случае, если файл открыт с помощью меню.Кроме того, в строке состояния имеется постоянный виджет, отображающий информацию.

В моем приложении есть состояния:

  1. Перед открытием файла (в этом состоянии в строке состояния отображается что-то особенное, а кнопка «Пуск» отключена)
  2. Файл был открыт, но обработка не началась:кнопка «Пуск» включена, в строке состояния отображается что-то еще
  3. Обработка идет:на кнопке «Пуск» теперь написано «Стоп», а в строке состояния отображается прогресс.

В Wx у меня было бы событие обновления пользовательского интерфейса кнопки, обрабатывающее ее состояние:текст на нем и включен ли он в зависимости от состояния приложения.То же самое и со строкой состояния (или я бы использовал для этого EVT_IDLE).

В Qt мне приходится обновлять кнопку несколькими методами, которые могут влиять на состояние, или просто создавать метод update_ui и периодически вызывать его по таймеру.Какой способ более «QT»?

Это было полезно?

Решение

Использование EVT_UPDATE_UI в wxWidgets, кажется, подчеркивает одно из фундаментальных различий в том, как wxWidgets и Qt ожидают, что разработчики будут обрабатывать события в своем коде.

С помощью Qt вы соединяете сигналы и слоты между виджетами пользовательского интерфейса, либо обрабатывая «бизнес-логику» в каждом слоте, либо делегируя ее выделенному методу.Обычно вы не беспокоитесь о внесении отдельных изменений в каждый виджет в вашем графическом интерфейсе, поскольку любые запросы на перерисовку будут помещены в очередь событий и доставлены, когда управление вернется в цикл обработки событий.Некоторые события рисования можно даже объединить для повышения эффективности.

Таким образом, в обычном приложении Qt, где сигналы и слоты используются для обработки изменений состояния, в принципе нет необходимости иметь механизм простоя, который отслеживает состояние приложения и обновляет виджеты, поскольку эти обновления должны происходить автоматически.

Вам придется рассказать немного больше о том, что вы делаете, чтобы объяснить, почему вам нужен эквивалент этого события в Qt.

Другие советы

Я бы отправил сигналы Qt, чтобы указать изменения состояния (например.fileOpened, ProcessingStarted, ProcessingDone).Слоты в объектах, управляющих кнопкой «Пуск» и виджетом строки состояния (или подклассами), могут быть подключены к этим сигналам, а не «опросу» текущего состояния в событии простоя.

Если вы хотите, чтобы сигнал был отложен позже в цикле событий, а не сразу (например,потому что для того, чтобы что-то сделать, потребуется некоторое время), вы можете использовать соединение сигнального слота с «очередью», а не обычное соединение.

http://doc.trolltech.com/4.5/signalsandslots.html#signals

Тип соединения является необязательным параметром функции Connect():http://doc.trolltech.com/4.5/qobject.html#connect , http://doc.trolltech.com/4.5/qt.html#ConnectionType-enum

Насколько я понимаю, EVT_IDLE отправляется, когда очередь сообщений приложения пуста.В Qt такого события нет, но если вам нужно что-то выполнить в Qt, когда нет ожидающих событий, вам следует использовать QTimer с таймаутом 0.

В общем, более Qt-ish способ — обновлять кнопку/панель инструментов по мере необходимости в любых функциях, требующих обновления, или консолидировать некоторые функциональные возможности и напрямую вызывать эту функцию, когда она нужна программе (например, функция updateUi).

Вы должны знать, что в Qt изменение атрибута элемента Ui не вызывает немедленной перерисовки, а ставит перерисовку в очередь в системе событий, и несколько вызовов перерисовки сжимаются в один, где это возможно.

Что касается многочисленных изменений, касающихся состояния, взгляните на этот пост в блоге об ожидаемом дополнении к Qt, которое упростит обработку состояний.Похоже, это решит многие ваши жалобы, потому что в ваших многочисленных функциях вы можете просто перенести переменную состояния, и другие части пользовательского интерфейса должны обновиться в соответствии с этим.Не факт, что это попадет в следующий выпуск Qt (хотя я бы поспорил на это или что-то подобное), и я понятия не имею, насколько точно PyQt отслеживает выпуски Qt.Или, альтернативно, вы можете использовать эту концепцию и создать свой собственный класс для отслеживания состояния по мере необходимости.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top