

- 基於操作系統才能運行
- GUI應用程序提供的功能必須由用戶觸發
- 用戶操作界面時操作系統是第一個感知的
- 系統內核的消息通過事件處理轉變成QT的信號
誰來產生事件? 最容易想到的是我們的輸入設備,比如鍵盤、鼠標產生的keyPressEvent,keyReleaseEvent,mousePressEvent,mouseReleaseEvent事件(他們被封裝成QMouseEvent和QKeyEvent)。
②Qt中事件的分發
對於Qt GUI程序,由QApplication來負責
類是整個Qt對象模型的心臟,事件處理機制是QObject三大職責(內存管理、內省(intropection)與事件處理制)之一。任何一個想要接受並處理事件的對象均須繼承自QObject,可以選擇重載QObject::event()函數或事件的處理權轉給父類。
- Qt事件是一個QEvent(或子類)的對象
- 有時一個事件包含多個事件類型,比如鼠標事件又可以分為鼠標按下、雙擊、和移動多種操作
- 事件類型由QEvent類的枚舉型QEvent::Type來表示,可由幫助文檔進行查詢
- Qt事件用於描述程序內部或外部發生的對應動作(描述的是操作系統發生來的消息,一個系統消息對應着一個消息事件)
- 任意QObject對象都具備時間處理的能力
QEvent及其子類對象
note:QEvent子類可以表示一個事件,但並不能處理這個事件
Qt 程序需要在main()函數創建一個QApplication對象,然后調用它的exec()函數。這個函數就是開始 Qt 的事件循環。在執行exec()函數之后,程序將進入事件循環來監聽應用程序的事件。當事件發生時,Qt 將創建一個事件對象。Qt 中所有事件類都繼承於QEvent。在事件對象創建完畢后,Qt 將這個事件對象傳遞給QObject的event()函數。event()函數並不直接處理事件,而是將這些事件對象按照它們不同的類型,分發給不同的事件處理器(event handler)。如上所述,event()函數主要用於事件的分發。
- Qt事件產生后會立即被分發到QWidget對象(QObject的子類,如按鍵QPushButton對象等)
- QWidget對象其內部會有一個event(QEVent*)函數被調用,進行事件處理
- event()根據事件類型調用不同的事件處理函數(默認的子函數)
- 在事件處理函數中發送Qt中預定義的信號
- 調用信號關聯的槽函數
(4) QPushButton事件處理分析
①接收到鼠標事件
②QApplication調用QObject::event(QEvent*)成員函數來處理,進行事件的分派。
③調用QPushButton的mouseReleaseEvent(QMouseEvent*)成員函數
④QPushButton調用click()成員函數
⑤觸發信號SIGNAL(clicked())
(5)實例
實例一:自定義事件處理函數
鼠標左鍵右鍵
wigth.h
1 #ifndef WIDGET_H 2 #define WIDGET_H
3 4 #include <QWidget>
5 6 class Widget : public QWidget 7 { 8 Q_OBJECT 9 protected: 10 void mousePressEvent(QMouseEvent *event); 11 public: 12 Widget(QWidget *parent = 0); 13 14 ~Widget(); 15 }; 16 17 #endif // WIDGET_H
18 19
20
widgth.cpp
1 #include "widget.h"
2 #include <QMouseEvent>
3 #include <QDebug>
4 #include <QMenu>
5 Widget::Widget(QWidget *parent) 6 : QWidget(parent) 7 { 8 } 9 10 void Widget::mousePressEvent(QMouseEvent *event) 11 { 12 if(event->button()==Qt::LeftButton) 13 { 14 qDebug()<<"LeftButton clicked!"; 15 } 16 else if(event->button()==Qt::RightButton) 17 { 18 qDebug()<<"RightButton clicked!"; 19
20 } 21 22 } 23 24 Widget::~Widget() 25 { 26
27 } 28
main.cpp
1 #include <QApplication>
2 #include "widget.h"
3 4 int main(int argc, char *argv[]) 5 { 6 QApplication a(argc, argv); 7 Widget w; 8 w.show(); 9
10 return a.exec(); 11 } 12
1 #ifndef _QMYPUSHBUTTON_H_ 2 #define _QMYPUSHBUTTON_H_
3
4 #include <QPushButton>
5
6 typedef void (QButtonListener)(QObject*,QMouseEvent*); 7
8 class QMyPushButton : public QPushButton 9 { 10 Q_OBJECT 11
12 protected: 13 QButtonListener* m_listener; 14
15 //重寫QPushButton的事件處理函數 就有可能不會產生clicked信號
16 void mouseReleaseEvent(QMouseEvent *e); 17 public: 18 explicit QMyPushButton(QWidget* parent = 0, QButtonListener* listener = 0); 19 }; 20
21 #endif // _QMYPUSHBUTTON_H_
//QMyPushButton.cpp
1 #include "QMyPushButton.h"
2 #include <QMouseEvent>
3
4 QMyPushButton::QMyPushButton(QWidget* parent, QButtonListener* listener):QPushButton(parent) 5 { 6 m_listener = listener; 7 } 8
9 //重寫改寫事件處理函數,會改變程序的行為。
10 void QMyPushButton::mouseReleaseEvent(QMouseEvent *e) 11 { 12 if(m_listener != NULL) 13 { 14 //調用自定義的事件處理函數,盡管按鈕的clicked信號被連接到onMyButtonClicked槽函數, 15 //但因自定義的m_listener函數里並不觸發clicked信號,從而槽函數不會被調用。
16 m_listener(this, e); 17 e->accept();//事件被接收,就不再傳遞到父QWidget
18
19 setDown(false); //按鈕設置為“彈起”狀態
20 } 21 else
22 { 23 //父類的mouseReleaseEvent會去調用clicked(),並觸發SIGNAL(clicked()) 24 //從而調用到連接到該信號的槽函數(本例為onMyButtonClicked())
25 QPushButton::mouseReleaseEvent(e); //調用父類
26 } 27 }
Widget.h
1 #ifndef _WIDGET_H_ 2 #define _WIDGET_H_
3
4 #include <QWidget>
5 #include "QMyPushButton.h"
6
7 class Widget : public QWidget 8 { 9 Q_OBJECT 10 QMyPushButton myButton; 11
12 protected slots: 13 void onMyButtonClicked(); 14
15 public: 16 Widget(QWidget *parent = 0); 17 ~Widget(); 18 }; 19
20 #endif // _WIDGET_H_
Widget.cpp
1 #include "Widget.h"
2 #include <qDebug>
3
4 //自定義事件處理函數
5 void onMyButtonMouseRelease(QObject* sender, QMouseEvent* e) 6 { 7 qDebug() << "onMyButtonMouseRelease(QObject* sender, QMouseEvent* e)"; 8 } 9
10 Widget::Widget(QWidget *parent) 11 : QWidget(parent),myButton(this, onMyButtonMouseRelease) //實驗2:myButton(this, 0)
12 { 13 myButton.setText("QMyPushButton"); 14
15 connect(&myButton, SIGNAL(clicked()), this, SLOT(onMyButtonClicked())); 16 } 17
18 //槽函數,用於接收按鈕的clicked信號
19 void Widget::onMyButtonClicked() 20 { 21 qDebug() << "onMyButtonClicked()" ; 22 } 23
24 Widget::~Widget() 25 { 26 }
main.cpp
#include "Widget.h" #include <QApplication>
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
(4)事件(QEvent)和信號(SIGNAL)的不同
|
事件(QEvent) |
信號(SIGNAL) |
與QObject的關系 |
由具體對象進行處理 |
由具體對象主動產生 |
對程序影響 |
改寫事件處理函數可能導致程序行為發生改變 |
信號是否存在對應的槽函數不會改變程序行為 |
兩者的聯系 |
一般而言,信號在具體的事件處理函數中產生 |
例如:單擊界面上的按鈕,那么就會產生鼠標事件QMouseEvent(不是按鈕產生的),由於按鈕被按下了,所以他會發出一個單擊信號clicked()信號(是按鈕產生的),這里只考慮單擊信號而不用考慮鼠標事件,但如果要設計一個按鈕,或者當單擊按鈕時讓它產生別的效果,此時就要考慮鼠標事件了,由此,信號和事件是兩個不同層面的東西,發出者不同,作用不同。Qt中,所有的QObject的子類實例均可對事件接收和處理!
3. 小結
(1)Qt中的事件和信號不同
(2)事件由QObject對象進行處理
(3)信號由QObject對象觸發
(4)重寫事件處理函數可能改變程序行為
(5)信號的觸發不會對程序行為造成影響
(6)事件處理是在實際工程開發中應用非常普遍的