【Qt 拦截消息的五种方法】
- 覆写框架类QCoreApplication的notify函数,这个函数将得到整个框架中所有窗口的消息
- 给框架类安装一个消息过滤器 QCoreApplication->nativeEventFilter(filterObj),这种我们代码没有实现
- 给某窗口安装一个消息过滤器 QPushButton->installEventFilter(filterObj)
- 继承某窗口并覆写event函数(该函数负责某个窗口中派发所有子消息)
- 继承某窗口并覆写窗口的某个子消息
以上介绍的几种方法结构图如下:
【代码示例】
下面代码演示了上面介绍的 1、3、4、5 四种方法,由于第二种非常难演示并且与第一种功能类似,所以我们没有做示例。
代码一共分7个文件:
- capplication.h:继承 QApplication 的类 CApplication 类
- capplication.cpp:继承 QApplication 的类 CApplication 类的功能实现
- cpushbutton.h:继承 QPushButton 的类 CPushButton 类
- cpushbutton.cpp:继承 QPushButton 的类 CPushButton 类的功能实现
- cwidget.h:继承 QWidget 的类 CWidget 类
- cwidget.cpp:继承 QWidget 的类 CWidget 类的实现
- main.cpp:实例化框架和窗口对象并显示窗口
#ifndef CAPPLICATION_H #define CAPPLICATION_H #include <QApplication> #include <QDebug> class CApplication : public QApplication { public: CApplication(int argc, char* argv[]); bool notify(QObject *, QEvent *); }; #endif // CAPPLICATION_H
#include "capplication.h" CApplication::CApplication(int argc, char* argv[]) :QApplication(argc, argv) { } bool CApplication::notify(QObject *obj, QEvent *ev) { // 根据窗口名字判断是否是 CWidget 窗口类的消息 if (obj->objectName() == "widgets") { // 判断消息类型是不是鼠标点击消息 if (ev->type() == QEvent::MouseButtonPress) { qDebug() << "在窗口中点击了鼠标!"; } } // 将消息交还给父窗口处理,避免消息丢失 QApplication::notify(obj, ev); }
#ifndef CPUSHBUTTON_H #define CPUSHBUTTON_H #include <QPushButton> #include <QDebug> #include <QMouseEvent> class CPushButton : public QPushButton { public: CPushButton(); void mousePressEvent(QMouseEvent *e); void mouseReleaseEvent(QMouseEvent *e); }; #endif // CPUSHBUTTON_H
#include "cpushbutton.h" CPushButton::CPushButton() { } void CPushButton::mousePressEvent(QMouseEvent *e) { qDebug() << "截获鼠标按下消息..."; // 因为最底层的消息没有返回值 // 可以调用accept函数告知父类已经处理过该消息 e->accept(); } void CPushButton::mouseReleaseEvent(QMouseEvent *e) { qDebug() << "截获鼠标弹起消息..."; // 表示对此消息不感兴趣,交由父类的消息处理函数去处理。 // 实际我们已经在这个消息处理函数中打印了一句话 // 这样父类、子类都会对这个消息做处理 e->ignore(); }
#ifndef CWIDGET_H #define CWIDGET_H #include <QWidget> #include <QObject> #include <QEvent> #include "cpushbutton.h" class CWidget : public QWidget { Q_OBJECT public: explicit CWidget(QWidget *parent = 0); CPushButton* _button; bool eventFilter(QObject *, QEvent *); signals: public slots: }; #endif // CWIDGET_H
#include "cwidget.h" CWidget::CWidget(QWidget *parent) : QWidget(parent) { // 设置自身窗口的名字,好让父类可以识别这个窗口进行消息处理 this->setObjectName("widgets"); _button = new CPushButton; _button->setText("button"); _button->setParent(this); _button->installEventFilter(this); } bool CWidget::eventFilter(QObject *obj, QEvent *ev) { // 判断对象是否是 button 对象 if (obj == _button) { // 判断消息是否是单击消息 if (ev->type() == QEvent::MouseButtonPress) { // 对鼠标单击处理... } } // 把消息交还给父类处理,这样消息就不会丢失 QWidget::eventFilter(obj, ev); }
#include "capplication.h" #include "cwidget.h" int main(int argc, char* argv[]) { CApplication app(argc, argv); CWidget w; w.show(); return app.exec(); }