- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания QT 4 программирование GUI на С++ Жасмин Бланшет
Шрифт:
Интервал:
Закладка:
2. Мы можем переопределять функцию QObject::event().
Путем переопределения функции event() мы можем обрабатывать события до того, как они дойдут до обработчиков соответствующих событий. Этот подход очень хорош для изменения принятого по умолчанию поведения клавиши табуляции Tab, что было показано ранее. Он также используется для обработки редких событий, для которых не предусмотрены отдельные обработчики событий (например, QEvent::HoverEnter). При переопределении функции event() нам необходимо вызывать функцию базового класса event() для обработки тех событий, которые мы сами не обрабатываем.
3. Мы можем устанавливать фильтр событий для отдельного объекта QObject.
После регистрации объекта с помощью функции installEventFilter() все события целевого объекта сначала передаются функции контролирующего объекта eventFilter(). Если для одного объекта установлено несколько фильтров, они действуют поочередно, начиная с того, который установлен последним, и кончая тем, который установлен первым.
4. Мы можем устанавливать фильтр событий для объекта QApplication.
После регистрации фильтра для qApp (уникальный объект типа QApplication) каждое событие каждого объекта приложения передается функции eventFilter() до его передачи любым другим фильтрам событий. Этот подход очень удобен для отладки. Он может также использоваться для обработки событий мышки, посылаемых для отключенных виджетов, которые обычно отклоняются QApplication.
5. Мы можем создать подкласс QApplication и переопределить функцию notify().
Qt вызывает QApplication::notify() для генерации события. Переопределение этой функции представляет собой единственный способ получения доступа ко всем событиям до того, как ими займутся фильтры событий. Пользоваться фильтрами событий, как правило, удобнее, поскольку параллельно может существовать любое количество фильтров событий и только одна функция notify().
События многих типов, в том числе события мышки и клавиатуры, могут передаваться дальше по системе объектов приложения. Если событие не было обработано ни на пути к целевому объекту, ни самим целевым объектом, процесс обработки события повторяется, но теперь в качестве нового целевого объекта используется родительский объект. Этот процесс продолжается, управление передается от одного родительского объекта к другому до тех пор, пока либо событие не будет обработано, либо не будет достигнут объект самого верхнего уровня.
Рис. 7.2. Передача события в диалоговом окне.
На рис. 7.2 показано, как событие нажатия клавиши пересылается в диалоговом окне от дочернего объекта к родительскому. Когда пользователь нажимает клавишу на клавиатуре, сначала событие передается виджету, на котором установлен фокус — в данном случае это расположенный в нижнем правом углу флажок QCheckBox. Если QCheckBox не обрабатывает это событие, Qt передает его объекту QGroupBox и в конце концов объекту QDialog.
Обработка событий во время продолжительных процессов
Когда мы вызываем QApplication::exec(), тем самым начинаем цикл обработки событий Qt. При запуске пpилoжeния Qt генерирует несколько событий для отображения на экране виджетов. После этого начинает выполняться цикл обработки событий: постоянно проверяется их возникновение, и эти события отправляются к объектам QObject данного приложения.
Во время обработки события могут генерироваться другие события, которые ставятся в конец очереди событий Qt. Если слишком много времени уходит на обработку одного события, интерфейс пользователя становится невосприимчивым к действиям пользователя. Например, любые сгенерированные оконной системой события во время сохранения файла на диск не будут обрабатываться до тех пор, пока весь файл не будет записан. В ходе записи файла приложение не будет отвечать на запросы оконной системы на перерисовку приложения.
Одно из решений заключается в применении многопоточной обработки: один процесс для работы с интерфейсом пользователя приложения и другой процесс для выполнения операции сохранения файла (или любой другой длительной операции). В этом случае интерфейс пользователя приложения сможет реагировать на события в процессе выполнения операции сохранения файла. Мы рассмотрим способы обеспечения такого режима работы в главе 18.
Более простое решение заключается в выполнении частых вызовов функции QApplication::processEvents() в программном коде сохранения файла. Данная функция говорит Qt о необходимости обработки ожидающих в очереди событий и затем возвращает управление вызвавшей ее функции. Фактически функция QApplication::exec() представляет собой не более чем вызов функции processEvents() в цикле while.
Ниже приводится пример того, как мы можем сохранить работоспособность интерфейса пользователя при помощи функции processEvents(), причем за основу взят программный код сохранения файла в приложении Spreadsheet:
01 bool Spreadsheet::writeFile(const QString &fileName)
02 {
03 QFile file(fileName);
04 …
05 for (int row = 0; row < RowCount; ++row) {
06 for (int column = 0; column < ColumnCount; ++column) {
07 QString str = formula(row, column);
08 if (!str.isEmpty())
09 out << quint16(row) << quint16(column) << str;
10 }
11 qApp->processEvents();
12 }
13 return true;
14 }
При использовании этого метода существует опасность того, что пользователь может закрыть главное окно во время выполнения операции сохранения файла или даже выбрать повторно File | Save, что приведет к непредсказуемому результату. Наиболее простое решение заключается в замене вызова
qApp->processEvents();
на вызов
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
который указывает Qt на необходимость игнорирования событий мышки и клавиатуры.
Часто нам хочется показывать индикатор состояния процесса QProgressDialog в ходе выполнения продолжительной операции. QProgressDialog имеет полоску индикатора, информирующую пользователя о ходе выполнения операции приложением. QProgressDialog также содержит кнопку Cancel, которая позволяет пользователю прекратить выполнение операции. Ниже приводится программный код, применяющий данный подход при сохранении файла приложения Электронная таблица:
01 bool Spreadsheet::writeFile(const QString &fileName)
02 {
03 QFile file(fileName);
04 …
05 QProgressDialog progress(this);
07 progress.setLabelText(tr("Saving %1").arg(fileName));
08 progress.setRange(0, RowCount);
09 progress.setModal(true);
10 for (int row = 0; row < RowCount; ++row) {
11 progress.setValue(row);
12 qApp->processEvents();
13 if (progress.wasCanceled()) {
14 file.remove();
15 return false;
16 }
17 for (int column = 0; column < ColumnCount; ++column) {
18 QString str = formula(row, column);
19 if (!str.isEmpty())
20 out << quint16(row) << quint16(column) << str;
21 }
22 }
23 return true;
24 }
Мы создаем QProgressDialog, в котором RowCount является общим количеством шагов. Затем при обработке каждой строки мы вызываем функцию setValue() для обновления состояния индикатора. QProgressDialog автоматически вычисляет процент завершения операции путем деления текущего значения индикатора на общее количество шагов. Мы вызываем функцию QApplication::processEvents() для обработки любых событий перерисовки либо нажатия пользователем кнопки мышки или клавиши клавиатуры (например, чтобы разрешить пользователю нажимать кнопку Cancel). Если пользователь нажимает кнопку Cancel, мы прекращаем операцию сохранения файла и удаляем файл.
Мы не вызываем для QProgressDialog функцию show(), так как индикатор состояния сам делает это. Если оказывается так, что операция выполняется быстро, прежде всего из-за малого размера файла или высокого быстродействия компьютера, QProgressDialog обнаружит это и вообще не станет выводить себя на экран.
Кроме многопоточности и применения QProgressDialog существует совершенно другой способ работы с продолжительными операциями. Вместо выполнения заданной обработки сразу по поступлении запроса пользователя мы можем отложить эту обработку до момента перехода приложения в состояние ожидания. Этим способом можно пользоваться в тех случаях, когда обработку можно легко прерывать и затем возобновлять, поскольку мы не можем предсказать, как долго приложение будет в состоянии ожидания.