Qt中的事件处理
文章目錄
- 1 Qt中的事件處理
- 1.1 Qt中的事件處理過程
- 1.2 Qt中事件的傳遞過程
- 1.3 Qt中的事件過濾器
1 Qt中的事件處理
1.1 Qt中的事件處理過程
GUI程序原理回顧,圖形界面應(yīng)用程序的消息處理模型如下:
思考:操作系統(tǒng)發(fā)送的消息如何轉(zhuǎn)變成Qt信號(hào)?
Qt平臺(tái)將系統(tǒng)產(chǎn)生的消息轉(zhuǎn)換成Qt事件:
- Qt事件是一個(gè)QEvent的對(duì)象。
- Qt事件用于描述程序內(nèi)部或外部發(fā)生的動(dòng)作。
- 任意的QObject對(duì)象都具備事件處理的能力。
GUI應(yīng)用程序的事件處理方式:
場(chǎng)景分析:按鈕點(diǎn)擊
(圖中的序號(hào)4應(yīng)該在序號(hào)5之后。)
QPushButton事件處理分析:
事件(QEvent)和信號(hào)(SIGNAL)的不同:
- 事件由具體對(duì)象進(jìn)行處理,而信號(hào)是由對(duì)象在進(jìn)行事件處理的過程中主動(dòng)產(chǎn)生的。
- 改寫事件處理函數(shù)可能導(dǎo)致程序行為發(fā)生改變,但是信號(hào)是否存在對(duì)應(yīng)的槽函數(shù)不會(huì)改變程序行為。
- 一般而言,信號(hào)在具體的事件處理函數(shù)中產(chǎn)生。
編程實(shí)驗(yàn):自定義事件處理函數(shù)(改寫按鈕的點(diǎn)擊事件)
QMyPushButton.h:
QMyPushButton.cpp:
#include "QMyPushButton.h" #include <QMouseEvent>QMyPushButton::QMyPushButton(QWidget* parent, QButtonListener* listener) : QPushButton(parent) {m_listener = listener; }void QMyPushButton::mouseReleaseEvent(QMouseEvent *e) {if( m_listener != NULL ){m_listener(this, e);e->accept();setDown(false);}else{QPushButton::mouseReleaseEvent(e);} }Widget.h:
#ifndef _WIDGET_H_ #define _WIDGET_H_#include <QtGui/QWidget> #include "QMyPushButton.h"class Widget : public QWidget {Q_OBJECTQMyPushButton myButton; protected slots:void onMyButtonClicked(); public:Widget(QWidget *parent = 0);~Widget(); };#endif // _WIDGET_H_Widget.cpp:
#include "Widget.h" #include <QDebug>void onMyButtonMouseRelease(QObject* sender, QMouseEvent* e) {qDebug() << "onMyButtonMouseRelease(QObject* sender, QMouseEvent* e)"; }Widget::Widget(QWidget *parent) : QWidget(parent), myButton(this, onMyButtonMouseRelease) {myButton.setText("QMyPushButton");connect(&myButton, SIGNAL(clicked()), this, SLOT(onMyButtonClicked())); }void Widget::onMyButtonClicked() {qDebug() << "onMyButtonClicked()"; }Widget::~Widget() {}main.cpp:
#include <QtGui/QApplication> #include "Widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }1.2 Qt中事件的傳遞過程
首先我們需要了解一點(diǎn):事件被組件對(duì)象處理后可能傳遞到其父組件對(duì)象,也可能不傳遞到父組件對(duì)象。
QEvent中的關(guān)鍵成員函數(shù):
- void ignore():接收者忽略當(dāng)前事件,事件可能會(huì)傳遞給父組件。
- void accept():接收者期望處理當(dāng)前事件。
- bool isAccepted():判斷當(dāng)前事件是否被處理。
編程實(shí)驗(yàn):事件處理的順序
MyLineEdit.h:
MyLineEdit.cpp:
#include "MyLineEdit.h" #include <QDebug> #include <QEvent> #include <QKeyEvent>MyLineEdit::MyLineEdit(QWidget *parent) :QLineEdit(parent) { }bool MyLineEdit::event(QEvent* e) {if( e->type() == QEvent::KeyPress ){qDebug() << "MyLineEdit::event";}return QLineEdit::event(e); }void MyLineEdit::keyPressEvent(QKeyEvent* e) {qDebug() << "MyLineEdit::keyPressEvent";QLineEdit::keyPressEvent(e);// e->ignore(); // 如果調(diào)用了ignore函數(shù),事件則會(huì)被傳遞到其父組件 }Widget.h:
#ifndef WIDGET_H #define WIDGET_H#include <QtGui/QWidget> #include "MyLineEdit.h"class Widget : public QWidget {Q_OBJECTMyLineEdit myLineEdit; public:Widget(QWidget* parent = 0);bool event(QEvent* e);void keyPressEvent(QKeyEvent* e);~Widget(); };#endif // WIDGET_HWidget.cpp:
#include "Widget.h" #include <QDebug> #include <QEvent>Widget::Widget(QWidget *parent): QWidget(parent), myLineEdit(this) {}bool Widget::event(QEvent* e) {if( e->type() == QEvent::KeyPress ){qDebug() << "Widget::event";}return QWidget::event(e); }void Widget::keyPressEvent(QKeyEvent* e) {qDebug() << "Widget::keyPressEvent";QWidget::keyPressEvent(e); }Widget::~Widget() {}main.cpp:
#include <QtGui/QApplication> #include "Widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }1.3 Qt中的事件過濾器
對(duì)于Qt中的事件過濾器:
- 事件過濾器可以對(duì)其他組件接收到的事件進(jìn)行監(jiān)控。
- 任意的QObject對(duì)象都可以作為事件過濾器使用。
- 事件過濾器對(duì)象需要重寫eventFilter()函數(shù)。
組件通過installEventFilter()函數(shù)安裝事件過濾器:
- 事件過濾器在組件之前接收到事件。
- 事件過濾器能夠決定是否將事件轉(zhuǎn)發(fā)到組件對(duì)象。
事件過濾器的典型實(shí)現(xiàn):
編程實(shí)驗(yàn):事件過濾器的使用
大部分代碼和上面的代碼都相同,這里只貼出安裝事件過濾器、和事件過濾器的實(shí)現(xiàn):
參考資料:
總結(jié)
- 上一篇: Qt中的QMap和QHash
- 下一篇: 双向链表数据结构