QT 4: программирование GUI на С++
Шрифт:
Установка фильтров событий
Одним из действительно эффективных средств в модели событий Qt является возможность с помощью некоторого экземпляра объекта QObject контролировать события другого экземпляра объекта QObject еще до того, как они дойдут до последнего.
Предположим, что наш виджет CustomerInfoDialog состоит из нескольких редакторов строк QLineEdit и мы хотим использовать клавишу Space (пробел) для передачи фокуса следующему QLineEdit. Такой необычный режим работы может оказаться полезным для разработки, предназначенной для собственных нужд, и когда пользователи
Этот подход имеет один основной недостаток: если мы используем в форме несколько различных видов виджетов (например, QComboBox и QSpinBox), мы должны также создать их подклассы для обеспечения единообразного поведения. Лучшее решение заключается в перехвате виджетом CustomerInfoDialog событий нажатия клавиш клавиатуры своих дочерних виджетов и в обеспечении необходимого поведения в его программном коде. Это можно сделать при помощи фильтров событий. Настройка фильтров событий сострит из двух этапов:
1. Зарегистрируйте объект—перехватчик с целевым объектом посредством вызова функции installEventFilter для целевого объекта.
2. Выполните обработку событий целевого объекта в функции eventFilter перехватчика.
Регистрацию объекта контроля удобно выполнять в конструкторе CustomerInfoDialog:
После регистрации фильтра события те из них, которые посылаются виджетам firstNameEdit, lastNameEdit, cityEdit и phoneNumberEdit, сначала будут переданы функции eventFilter виджета CustomerInfoDialog и лишь затем дойдут по своему прямому назначению. (Если для одного объекта установлено несколько фильтров событий, они вызываются по очереди, начиная с установленного последним и последовательно возвращаясь к первому.)
Ниже приводится функция eventFilter, которая перехватывает события:
Во-первых,
Если целевым виджетом не является QLineEdit или если событие не вызвано нажатием клавиши Space, мы передаем управление функции базового класса eventFilter. Целевым виджетом мог бы быть также некоторый виджет, базовый класс которого QDialog осуществляет контроль. (В Qt 4.1 этого не происходит с QDialog. Однако другие классы виджетов в Qt, например QScrollArea, контролируют по различным причинам некоторые свои дочерние виджеты.)
Qt предусматривает пять уровней обработки и фильтрации событий:
1. Мы можем переопределять конкретный обработчик событий.
Переопределение таких обработчиков событий, как mousePressEvent, keyPressEvent и paintEvent, представляет собой очень распространенный способ обработки событий. Мы уже видели много примеров такой обработки.
2. Мы можем переопределять функцию QObject::event.
Путем переопределения функции event мы можем обрабатывать события до того, как они дойдут до обработчиков соответствующих событий. Этот подход очень хорош для изменения принятого по умолчанию поведения клавиши табуляции Tab, что было показано ранее. Он также используется для обработки редких событий, для которых не предусмотрены отдельные обработчики событий (например, QEvent::HoverEnter). При переопределении функции event нам необходимо вызывать функцию базового класса event для обработки тех событий, которые мы сами не обрабатываем.
3. Мы можем устанавливать фильтр событий для отдельного объекта QObject.
После регистрации объекта с помощью функции installEventFilter все события целевого объекта сначала передаются функции контролирующего объекта eventFilter. Если для одного объекта установлено несколько фильтров, они действуют поочередно, начиная с того, который установлен последним, и кончая тем, который установлен первым.
4. Мы можем устанавливать фильтр событий для объекта QApplication.
После регистрации фильтра для qApp (уникальный объект типа QApplication) каждое событие каждого объекта приложения передается функции eventFilter до его передачи любым другим фильтрам событий. Этот подход очень удобен для отладки. Он может также использоваться для обработки событий мышки, посылаемых для отключенных виджетов, которые обычно отклоняются QApplication.
5. Мы можем создать подкласс QApplication и переопределить функцию notify.