事件過濾器(eventFilter)

Qt創建了QEvent之後,會調用QObject的event()函數進行事件的分發,我們可以在event()函數中實現想要的操作,但如果元件很多,就需要多次重載event()函數,顯然是非常沒有效率且沒什麼維護性的方法。

Qt提供了事件過濾器(eventFilter()):

  • virtual bool QObject::eventFilter ( QObject * watched, QEvent * event );

它會檢查接收到的事件,如果這個事件是我們感興趣的類型,就進行我們自己的處理,如果不是,就繼續轉發,這邊以繼承自QWidget的自定義Widget元件,重載原本的eventFilter()函式,當我們按下Up或Down鍵,此時LineEdit上會顯示按下的鍵。


widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QKeyEvent>
#include <QLineEdit>
#include <QVBoxLayout>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    bool eventFilter(QObject *obj, QEvent *event);
private:
    QLineEdit *upLineEdit;
    QLineEdit *downLineEdit;
    QVBoxLayout *mainLayout;
};

#endif 

widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent)
{
    setWindowTitle(tr("事件過濾器"));
    upLineEdit = new QLineEdit(this);
    downLineEdit = new QLineEdit(this);
    mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(upLineEdit);
    mainLayout->addWidget(downLineEdit);
    upLineEdit->installEventFilter(this);
    downLineEdit->installEventFilter(this);
}

bool Widget::eventFilter(QObject *obj, QEvent *event){
    if(obj==upLineEdit || obj==downLineEdit) {
        if(event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if(keyEvent->key() == Qt::Key_Up) {
                upLineEdit->setText(tr("Up鍵被按下"));
                downLineEdit->setText(tr(""));
                return true;
            }
            if(keyEvent->key() == Qt::Key_Down) {
                upLineEdit->setText(tr(""));
                downLineEdit->setText(tr("Down鍵被按下"));
                return true;
            }
        }
        else{
            return QWidget::eventFilter(obj, event);
        }
    }
    else{
        return QWidget::eventFilter(obj, event); //對於不關心的事件,返回父類的eventFilter()函數
    }
}

main.cpp

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.resize(200,200);
    w.show();

    return a.exec();
}