1. 程式人生 > >QT如何捕獲全域性的鍵盤事件?

QT如何捕獲全域性的鍵盤事件?

QT如何捕獲全域性的鍵盤事件?

方法一:繼承QApplication類,並重載notify()函式

Qt是用QApplication::notify()函式來分發事件的。想要在任何事件過濾器檢視任何事件之前先得到這些事件,過載這個函式是唯一的辦法。通常來說事件過濾器更好用一些, 因為不需要去繼承QApplication類。而且可以給QApplication物件安裝任意個數的事件過濾器,相比之下, notify()函式只有一個。

程式碼如下:

class MyApplication : public QApplication

{

public:

     MyApplication(int&argc,char **argv);

     bool notify(QObject*, QEvent *);

     void setWindowInstance(MainWindow*wnd);

private:

     MainWindow* window;//儲存一個你窗體的指標

};

 

MyApplication::MyApplication(int &argc,char **argv):

QApplication(argc,argv),window(0)

{

 

}

 

void MyApplication::setWindowInstance(MainWindow *wnd)

{

     window = wnd;

}

 

bool MyApplication::notify(QObject *obj, QEvent *e)

{

     const QMetaObject* objMeta = obj->metaObject();
     QString clName = objMeta->className();

     if((e->type() == QEvent::KeyPress) && (clName != "QLineEdit"))
     {

 

          if(window)

          {

                QKeyEvent*keyEvent = static_cast<QKeyEvent *>(e);

                window->keyPress(keyEvent);

          }

     }

     return QApplication::notify(obj,e);

}

 

注:

Qt的事件和Qt中的signal不一樣. 後者通常用來"使用"widget, 而前者用來"實現" widget. 比如一個按鈕, 我們使用這個按鈕的時候, 我們只關心他clicked()的signal, 至於這個按鈕如何接收處理滑鼠事件,再發射這個訊號,我們是不用關心的. 但是如果我們要過載一個按鈕的時候,我們就要面對event了. 比如我們可以改變它的行為,在滑鼠按鍵按下的時候(mouse press event) 就觸發clicked()的signal而不是通常在釋放的( mouse release event)時候.

 

事件的產生

事件的兩種來源:

       一種是系統產生的;通常是window system把從系統得到的訊息,比如滑鼠按鍵,鍵盤按鍵等, 放入系統的訊息佇列中. Qt事件迴圈的時候讀取這些事件,轉化為QEvent,再依次處理.

       一種是由Qt應用程式程式自身產生的.程式產生事件有兩種方式, 一種是呼叫QApplication::postEvent(). 例如QWidget::update()函式,當需要重新繪製螢幕時,程式呼叫update()函式,new出來一個paintEvent,呼叫QApplication::postEvent(),將其放入Qt的訊息佇列中,等待依次被處理.另一種方式是呼叫sendEvent()函式. 這時候事件不會放入佇列, 而是直接被派發和處理, QWidget::repaint()函式用的就是這種方式.

 

事件的派發和處理

首先說明Qt中事件過濾器的概念. 事件過濾器是Qt中一個獨特的事件處理機制, 功能強大而且使用起來靈活方便. 通過它, 可以讓一個物件偵聽攔截另外一個物件的事件. 事件過濾器是這樣實現的: 在所有Qt物件的基類: QObject中有一個型別為QObjectList的成員變數,名字為eventFilters,當某個QObjec (qobjA)給另一個QObject (qobjB)安裝了事件過濾器之後, qobjB會把qobjA的指標儲存在eventFilters中.在qobjB處理事件之前,會先去檢查eventFilters列表, 如果非空, 就先呼叫列表中物件的eventFilter()函式.一個物件可以給多個物件安裝過濾器. 同樣, 一個物件能同時被安裝多個過濾器, 在事件到達之後, 這些過濾器以安裝次序的反序被呼叫. 事件過濾器函式( eventFilter() ) 返回值是bool型, 如果返回true, 則表示該事件已經被處理完畢, Qt將直接返回, 進行下一事件的處理; 如果返回false, 事件將接著被送往剩下的事件過濾器或是目標物件進行處理.

Qt中,事件的派發是從QApplication::notify() 開始的, 因為QAppliction也是繼承自QObject, 所以先檢查QAppliation物件, 如果有事件過濾器安裝在qApp上, 先呼叫這些事件過濾器. 接下來QApplication::notify() 會過濾或合併一些事件(比如失效widget的滑鼠事件會被過濾掉, 而同一區域重複的繪圖事件會被合併). 之後,事件被送到reciver::event() 處理.

同樣, 在reciver::event()中, 先檢查有無事件過濾器安裝在reciever上. 若有, 則呼叫之. 接下來,根據QEvent的型別, 呼叫相應的特定事件處理函式. 一些常見的事件都有特定事件處理函式, 比如:mousePressEvent(), focusOutEvent(),  resizeEvent(),paintEvent(), resizeEvent()等等. 在實際應用中,經常需要過載這些特定事件處理函式在處理事件. 但對於那些不常見的事件, 是沒有相對應的特定事件處理函式的. 如果要處理這些事件, 就需要使用別的辦法, 比如過載event() 函式, 或是安裝事件過濾器.

 

 

http://blog.csdn.net/cpeasant_eva/article/details/43160549