Qt中使用事件過濾器來處理鍵盤焦點

我們都知道,在主事件循環中,使用QApplication::notify(QObject*, QEvent*)來分發事件到下面的子窗口,而子窗口將調用QObject::event(QEvent*)來根據事件類型調用相應的事件處理函數。在處理鍵盤焦點的時候,我們把焦點定位特殊部件的習慣通常是Tap鍵、下一個鍵盤快捷鍵或者鼠標滾輪等等,根據傳統的方法,爲了能夠正確切換焦點,我們需要重寫每個部件的鍵盤處理函數,在鍵盤處理函數中將焦點定位到特定位置,例如在主窗口中有很多的QPushButton按鈕,爲了使得每次按下一個鍵盤快捷鍵的時候能夠將焦點切換到下一個QPushButton上,我們需要重寫QPushButton的keyPressEvent事件處理函數,如下:


void MyButton::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_Down)
        focusNextChild();
    else
        QPushButton::keyPressEvent(event);  //如果不是按下一個鍵盤快捷鍵就直接使用父類QPushButton的該事件處理函數
}

這需要我們繼承QPushButton重新構造一個button類。在使用Qt Designer的時候,這種方法似乎不太好用,此時,我們可以使用事件過濾器來處理鍵盤焦點。


事件過濾器的思想是:讓一個對象監聽其它對象的時間。假設有對象A和對象B,讓對象A來監聽對象B的事件,我們且稱A爲監視器,如果想要A來監視B的事件,我們首先需要在B中註冊監視器A,即調用B->installEventFilter(&B),而在監視器A中有一個函數eventFilter(QObject*, QEvent*)專門用來處理A監視到的事件,也就是說,所有被A監視的對象上所發生的事件在送至其目的對象之前都需要先調用監視器中的eventFilter函數。如下一個例子:在一個widget上面有7個QPushButton,我們希望每次按下下一個鍵盤快捷鍵的時候能夠將焦點定位到下一個QPushButton上,就想平時我們常用的Tab鍵那樣。


思路:


1、首先弄清楚,監視器爲widget,被監視者爲7個QPushButton;


2、7個QPushButton都需要註冊監視器widget;


    ui->pushButton_1->installEventFilter(this);
    ui->pushButton_2->installEventFilter(this);
    ui->pushButton_3->installEventFilter(this);
    ui->pushButton_4->installEventFilter(this);
    ui->pushButton_5->installEventFilter(this);
    ui->pushButton_6->installEventFilter(this);


3、重寫監視器widget中的eventFilter來處理監視到的事件;


bool Widget::eventFilter(QObject *target, QEvent *event)
{
    if(target == ui->pushButton_1 || target == ui->pushButton_2 ||
       target == ui->pushButton_3 || target == ui->pushButton_4 ||
       target == ui->pushButton_5 || target == ui->pushButton_6 || target == ui->pushButton_7)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if(keyEvent->key() == Qt::Key_0)  //將event轉換爲QKeyEvent,然後判斷是否鍵
            {
                focusNextChild();
                return true;
            }
        }
    }
    return QWidget::eventFilter(target, event);  //假如並不是7個按鈕上的按下下一個鍵盤快捷鍵事件,就使用父類的eventFilter
}


所有的代碼如下:


widget.h


#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QEvent>
#include <QKeyEvent>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT
    
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    
protected:
    bool eventFilter(QObject *, QEvent *);

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H


widget.cpp


#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->pushButton_1->installEventFilter(this);
    ui->pushButton_2->installEventFilter(this);
    ui->pushButton_3->installEventFilter(this);
    ui->pushButton_4->installEventFilter(this);
    ui->pushButton_5->installEventFilter(this);
    ui->pushButton_6->installEventFilter(this);
}

bool Widget::eventFilter(QObject *target, QEvent *event)
{
    if(target == ui->pushButton_1 || target == ui->pushButton_2 ||
       target == ui->pushButton_3 || target == ui->pushButton_4 ||
       target == ui->pushButton_5 || target == ui->pushButton_6 || target == ui->pushButton_7)
    {
        if(event->type() == QEvent::KeyPress)
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
            if(keyEvent->key() == Qt::Key_0)  //將event轉換爲QKeyEvent,然後判斷是否鍵
            {
                focusNextChild();
                return true;
            }
        }
    }
    return QWidget::eventFilter(target, event);  //假如並不是7個按鈕上的按下下一個鍵盤快捷鍵事件,就使用父類的eventFilter
}

Widget::~Widget()
{
    delete ui;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章