Шаг 130.
Библиотека Qt.
Реализация фильтров событий

    На этом шаге рассмотрим реализацию фильтров событий.

    Как правило, событие передается тому объекту, над которым было осуществлено действие, но иногда требуется его обработка в другом объекте.

    В библиотеке Qt предусмотрен очень мощный механизм перехвата событий, который позволяет объекту фильтра просматривать события раньше объекта, которому они предназначены, и принимать решение по своему усмотрению — обрабатывать их и/или передавать дальше.

    Такой мониторинг осуществляется с помощью метода QObject::installEventFilter(), в который передается указатель на объект, осуществляющий фильтрацию событий.

    Важно то, что установка фильтров событий происходит не на уровне классов, а на уровне самих объектов. Это дает возможность вместо того, чтобы наследовать класс или изменять уже имеющийся (что не всегда возможно), просто воспользоваться объектом фильтра. Для настройки на определенные события необходимо создать класс фильтра, установив его в нужном объекте. Все получаемые события и их обработка будут касаться только тех объектов, в которых будут установлены фильтры.

    Фильтры событий можно использовать, например, в тех случаях, когда нужно добавить функциональность к каким-либо уже реализованным классам, не наследуя при этом каждый из них. После того как класс фильтра будет реализован, его объекты можно будет устанавливать в любых объектах, созданных от наследующих QObject классов. Это позволит сэкономить время на реализации, т. к. потребуется написать меньше кода, и вместе с тем значительно сократит временные затраты на отладку программы. Разработчику больше не надо заботиться о методах обработки событий для каждого из классов в отдельности, потому что это будет выполняться централизованно, одним классом фильтра, имеющим силу для всех объектов, в которых он был установлен.

    Чтобы реализовать класс фильтра, нужно унаследовать класс QObject и переопределить метод eventFilter(). Этот метод будет вызываться при каждом событии, предназначенном для объекта, в котором установлен фильтр событий до его получения. Метод имеет два параметра: первый — это указатель на объект, для которого предназначено событие, а второй — указатель на сам объект события.

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

    Пример, показанный на рис. 1, демонстрирует работу фильтра, который устанавливается в трех виджетах. Щелчок мыши на любом из них приводит к появлению окна сообщения, информирующего об имени класса виджета.


Рис.1. Программа, демонстрирующая перехват события

    Рассмотрим описание класса.

class MouseFilter : public QObject {
protected:
//прототип метода eventFilter() получает указатель на объект события
//и указатель на сам объект, для которого это событие предназначено
    virtual bool eventFilter(QObject*, QEvent*);
public:
    MouseFilter(QObject* pobj = 0);
};

    Рассмотрим реализацию метода eventFilter():

//метод eventFilter() отслеживает событие типа QEvent::MouseButtonPress,
соответствующее нажатию одной из кнопок мыши 
/*virtual*/bool MouseFilter::eventFilter(QObject* pobj, QEvent* pe)
{
  //если событие относится к этому типу,
    if (pe->type() == QEvent::MouseButtonPress) {
    //то выполняется преобразование указателя на объект события
    //к указателю типа QMouseEvent. Затем вызывается метод button()
    //класса QMouseEvent, чтобы узнать, какая из кнопок мыши была нажата.
    //Если была нажата левая кнопка,
        if (static_cast<QMouseEvent*>(pe)->button() == Qt::LeftButton) {
        //то в информационном окне сообщения выводится имя класса виджета,
        //возвращается значение true и событие дальше не передается 
            QString strClassName = pobj->metaObject()->className();
            QMessageBox::information(0, "Имя класса", strClassName);
            return true;
        }
    }
   //В остальных случаях возвращается значение false и событие передается дальше
    return false;
}

    Файлы приложения можно взять здесь.

    На следующем шаге рассмотрим искусственное создание событий.




Предыдущий шаг Содержание Следующий шаг