Саммерфилд Марк
Шрифт:
Обработка событий во время продолжительных процессов
Когда мы вызываем QApplication::exec, тем самым начинаем цикл обработки событий Qt. При запуске пpилoжeния Qt генерирует несколько событий для отображения на экране виджетов. После этого начинает выполняться цикл обработки событий: постоянно проверяется их возникновение, и эти события отправляются к объектам QObject данного приложения.
Во время обработки события могут генерироваться другие события, которые ставятся в конец очереди событий Qt. Если слишком много времени уходит на обработку одного события, интерфейс пользователя становится невосприимчивым к действиям пользователя. Например, любые сгенерированные оконной системой события во время сохранения файла на диск не будут обрабатываться до тех пор, пока весь файл не будет записан. В ходе записи файла приложение не будет отвечать на запросы оконной системы на перерисовку приложения.
Одно из решений заключается в применении многопоточной обработки: один процесс для работы с интерфейсом пользователя приложения и другой процесс для выполнения операции сохранения файла (или любой другой длительной операции). В этом случае интерфейс пользователя приложения сможет реагировать на события в процессе выполнения операции сохранения файла. Мы рассмотрим способы обеспечения такого режима работы в главе 18 .
Более простое решение заключается в выполнении частых вызовов функции QApplication::processEvents в программном коде сохранения файла. Данная функция говорит Qt о необходимости обработки ожидающих в очереди событий и затем возвращает управление вызвавшей ее функции. Фактически функция QApplication::exec представляет собой не более чем вызов функции processEvents в цикле while.
Ниже приводится пример того, как мы можем сохранить работоспособность интерфейса пользователя при помощи функции processEvents, причем за основу взят программный код сохранения файла в приложении Spreadsheet:
При использовании этого метода существует опасность того, что пользователь может закрыть главное окно во время выполнения операции сохранения файла или даже выбрать повторно File | Save, что приведет к непредсказуемому результату. Наиболее простое решение заключается в замене вызова
на вызов
который указывает Qt на необходимость игнорирования событий мышки и клавиатуры.
Часто нам хочется показывать индикатор состояния процесса QProgressDialog в ходе выполнения продолжительной операции. QProgressDialog имеет полоску индикатора, информирующую пользователя о ходе выполнения операции приложением. QProgressDialog также содержит кнопку Cancel, которая позволяет пользователю прекратить выполнение операции. Ниже приводится программный код, применяющий данный подход при сохранении файла приложения Электронная таблица:
Мы создаем QProgressDialog, в котором RowCount является общим количеством шагов. Затем при обработке каждой строки мы вызываем функцию setValue для обновления состояния индикатора. QProgressDialog автоматически вычисляет процент завершения операции путем деления текущего значения индикатора на общее количество шагов. Мы вызываем функцию QApplication::processEvents для обработки любых событий перерисовки либо нажатия пользователем кнопки мышки или клавиши клавиатуры (например, чтобы разрешить пользователю нажимать кнопку Cancel). Если пользователь нажимает кнопку Cancel, мы прекращаем операцию сохранения файла и удаляем файл.