http://www.cnblogs.com/venow/archive/2012/10/10/2718014.html
http://www.cnblogs.com/venow/archive/2012/10/10/2718019.html
http://www.cnblogs.com/venow/archive/2012/10/10/2718024.html
http://www.cnblogs.com/venow/archive/2012/10/11/2718026.html
http://www.cnblogs.com/venow/archive/2012/10/11/2718039.html
这篇博客写的非常清楚。最后总结一下Event 的截获顺序:
notiy > eventFilter > event > 默认的处理事件
------------------------------------------------------------------------------------------------
Qt事件处理(一)
从这章开始,我将简单实现Qt事件处理的五种方式,这五种方式的实现都是基于一个自定义的Button,我将它命名为MyButton。由于我是刚学Qt,有什么讲的不对的地方,请指正,不胜感激。
首先来看第一种事件处理:"重新实现特定的事件处理器",这种方式最简单,派生于一个组件,重新实现它的事件处理。这里我主要实现的是mousePressEvent、mouseReleaseEvent以及mouseMoveEvent这三个事件处理,而实现的方式都差不多,不同在于设置Button显示的文本。
mybutton.h的头文件如下:
#ifndef MYBUTTON_H #define MYBUTTON_H #include <QPushButton> #include <QMouseEvent> class MyButton : public QPushButton { protected: void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); }; #endif
mybutton.cpp的文件如下:
#include "mybutton.h" void MyButton::mousePressEvent(QMouseEvent *event) { this->setText(QString("Press: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); } void MyButton::mouseReleaseEvent(QMouseEvent *event) { this->setText(QString("Release: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); } void MyButton::mouseMoveEvent(QMouseEvent *event) { this->setText(QString("Move: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); }
main函数调用为:
#include <QtGui/QApplication> #include <QtCore/QTextCodec> #include "mybutton.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); QTextCodec::setCodecForTr(QTextCodec::codecForName("gb18030")); MyButton *button = new MyButton; button->setWindowTitle(QObject::tr("重新实现特定的事件处理器")); button->resize(400, 200); button->show(); return a.exec(); }
程序运行时,Button上的文本随着鼠标在不同的位置点击、释放以及左击拖动鼠标的不同而显示相应的文本。界面如下:
Qt事件处理(二)
Qt处理事件的第二种方式:"重新实现QObject::event()函数",通过重新实现event()函数,可以在事件到达特定的事件处理器之前截获并处理他们。这种方法可以用来覆盖已定义事件的默认处理方式,也可以用来处理Qt中尚未定义特定事件处理器的事件。当重新实现event()函数时,如果不进行事件处理,则需要调用基类的event()函数。
mybutton.h的文件如下:
#ifndef MYBUTTON_H #define MYBUTTON_H #include <QPushButton> #include <QMouseEvent> class MyButton : public QPushButton { protected: bool event(QEvent *e); void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); }; #endif
mybutton.cpp文件如下:
#include "mybutton.h" void MyButton::mousePressEvent(QMouseEvent *event) { this->setText(QString("Press: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); } void MyButton::mouseReleaseEvent(QMouseEvent *event) { this->setText(QString("Release: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); } void MyButton::mouseMoveEvent(QMouseEvent *event) { this->setText(QString("Move: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); } bool MyButton::event(QEvent *e) { if (e->type() == QEvent::MouseButtonPress) { QMouseEvent *event = static_cast<QMouseEvent*> (e); this->setText(QString("Press: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } else if (e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove) //屏蔽MouseButtonRelease和MouseMove事件 { return true; } return QPushButton::event(e); //其他事件调用基类的event()函数进行处理 }
运行程序,可以发现button的文本不管是点击、释放还是拖动鼠标,都只显示鼠标按下的文本,因为我们在event()函数里屏蔽了MouseButtonRelease和MouseMove事件。故事件是先经过event()函数,然后在到达特定的事件处理函数,程序运行界面为:
Qt事件处理(三)
Qt处理事件的第三种方式:"在QObject中注册事件过滤器",如果对象使用installEventFilter()函数注册了事件过滤器,目标对象中的所有事件将首先发给这个监视对象的eventFilter()函数。
mybutton.h文件如下:
#ifndef MYBUTTON_H #define MYBUTTON_H #include <QPushButton> #include <QMouseEvent> class MyButton : public QPushButton { protected: bool event(QEvent *e); }; #endif
mybutton.cpp文件如下:
#include "mybutton.h" bool MyButton::event(QEvent *e) { if (e->type() == QEvent::MouseButtonPress) { QMouseEvent *event = static_cast<QMouseEvent*> (e); this->setText(QString("Press: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } else if (e->type() == QEvent::MouseButtonRelease) { QMouseEvent *event = static_cast<QMouseEvent*> (e); this->setText(QString("Release: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } else if (e->type() == QEvent::MouseMove) { QMouseEvent *event = static_cast<QMouseEvent*> (e); this->setText(QString("Move: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } return QPushButton::event(e); //其他事件调用基类的event()函数进行处理 }
在这里,我们把button称为目标对象,MainWindow实现了eventFilter()函数,用MainWindow来监视button,称MainWindow为监视对象。
mainwindow.h文件如下:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QtGui/QMainWindow> #include "mybutton.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); protected: bool eventFilter(QObject *obj, QEvent *e); private: MyButton *button; }; #endif
mainwindow.cpp文件如下:
#include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { button = new MyButton; this->setCentralWidget(button); button->installEventFilter(this); //为button设置过滤器 } MainWindow::~MainWindow() { } bool MainWindow::eventFilter(QObject *obj, QEvent *e) { if (obj == button) { if (e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove) //屏蔽MouseButtonRelease和MouseMove事件 { return true; } else { return false; } } return QMainWindow::eventFilter(obj, e); }
运行程序,可以发现button的文本不管是点击、释放还是拖动鼠标,都只显示鼠标按下的文本,因为我们已经为button注册了事件过滤器,在监视对象MainWindow中,事件处理函数eventFilter()函数屏蔽了button的MouseButtonRelease和MouseMove事件。所以目标对象button的MouseButtonRelease和MouseMove事件得不到响应。
故事件是先经过监视对象的eventFilter()函数,然后在响应目标对象button的所有事件,程序运行界面为:
Qt事件处理(四)
Qt处理事件的第四种方式:"在QApplication中注册事件过滤器",如果一个事件过滤器被注册到程序中唯一的QApplication对象,应用程序中所有对象里的每一个事件都会在它们被送达其他事件事件过滤器之前,首先抵到这个eventFilter()函数。
在这里继承一个QWidget用来注册QApplication事件过滤器,MyWidget的头文件mywidget.h如下:
#ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> #include <QMouseEvent> class MyWidget : public QWidget { public: MyWidget(); protected: bool eventFilter(QObject *obj, QEvent *e); }; #endif
mywidget.cpp文件如下:
#include "mywidget.h" MyWidget::MyWidget() { } bool MyWidget::eventFilter(QObject *obj, QEvent *e) { //屏蔽MouseButtonPress、MouseButtonRelease和MouseMove事件 if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove) { return true; } return QWidget::eventFilter(obj, e); }
在这里,我们把button称为目标对象,MainWindow实现了eventFilter()函数,用MainWindow来监视button,称MainWindow为监视对象。
mainwindow.h文件如下:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QtGui/QMainWindow> #include <QPushButton> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); protected: bool eventFilter(QObject *obj, QEvent *e); private: QPushButton *button; }; #endif
mainwindow.cpp文件如下:
#include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { button = new QPushButton; this->setCentralWidget(button); button->installEventFilter(this); //为button设置过滤器 } MainWindow::~MainWindow() { } bool MainWindow::eventFilter(QObject *obj, QEvent *e) { if (obj == button) //响应button的MouseButtonPress、MouseButtonRelease和MouseMove事件 { if (e->type() == QEvent::MouseButtonPress) { QMouseEvent *event = static_cast<QMouseEvent*> (e); button->setText(QString("Press: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } else if (e->type() == QEvent::MouseButtonRelease) { QMouseEvent *event = static_cast<QMouseEvent*> (e); button->setText(QString("Release: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } else if (e->type() == QEvent::MouseMove) { QMouseEvent *event = static_cast<QMouseEvent*> (e); button->setText(QString("Move: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } else { return false; } } return QMainWindow::eventFilter(obj, e); }
运行程序,可以发现button不管是点击、释放还是拖动鼠标,都不会显示任何文本。因为我们已经为QApplication注册了事件过滤器,事件在到达button的监视对象MainWindow之前,会先到达QApplication的事件过滤器MyWidget的事件处理函数eventFilter()函数,该函数屏蔽了所有的MouseButtonPress、MouseButtonRelease和MouseMove事件。所以为button对象注册的事件过滤器不起作用。程序运行界面为:
Qt事件处理(五)
Qt处理事件的第五种方式:"继承QApplication并重新实现notify()函数"。Qt调用QApplication来发送一个事件,重新实现notify()函数是在事件过滤器得到所有事件之前获得它们的唯一方法。事件过滤器使用更为便利。因为可以同时有多个事件过滤器。而notify()函数只有一个。
重新实现的QApplication类MyApplication的头文件myapplication.h如下:
#ifndef MYAPPLICATION_H #define MYAPPLICATION_H #include <QApplication> #include <QEvent> class MyApplication : public QApplication { public: MyApplication(int & argc, char ** argv); public: bool notify(QObject *receiver, QEvent *e); }; #endif
myapplication.cpp文件如下:
#include "myapplication.h" #include <QMouseEvent> MyApplication::MyApplication(int & argc, char ** argv) : QApplication(argc, argv) { } bool MyApplication::notify(QObject *receiver, QEvent *e) { //屏蔽MouseButtonPress、MouseButtonRelease和MouseMove事件 if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease || e->type() == QEvent::MouseMove) { return true; } return QApplication::notify(receiver, e); }
mainwindow.h文件如下:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QtGui/QMainWindow> #include <QPushButton> #include <QMouseEvent> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); protected: bool eventFilter(QObject *obj, QEvent *e); private: QPushButton *button; }; #endif
mainwindow.cpp文件如下:
#include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { button = new QPushButton; this->setCentralWidget(button); } MainWindow::~MainWindow() { } bool MainWindow::eventFilter(QObject *obj, QEvent *e) { if (obj == button) //响应button的MouseButtonPress和MouseButtonRelease事件 { if (e->type() == QEvent::MouseButtonPress) { QMouseEvent *event = static_cast<QMouseEvent*> (e); button->setText(QString("Press: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } else if (e->type() == QEvent::MouseButtonRelease) { QMouseEvent *event = static_cast<QMouseEvent*> (e); button->setText(QString("Release: %1, %2").arg(QString::number(event->x()), QString::number(event->y()))); return true; } else { return false; } } return QMainWindow::eventFilter(obj, e); }
main.cpp文件如下:
#include <QtGui/QApplication> #include <QtCore/QTextCodec> #include "mainwindow.h" #include "myapplication.h" int main(int argc, char *argv[]) { MyApplication a(argc, argv); QTextCodec::setCodecForTr(QTextCodec::codecForName("gb18030")); MainWindow mainwindow; a.installEventFilter(&mainwindow); //为QApplication注册过滤器 mainwindow.setWindowTitle(QObject::tr("继承QApplication并重新实现notify()函数")); mainwindow.resize(400, 200); mainwindow.show(); return a.exec(); }
运行程序,可以发现button不管是点击、释放还是拖动鼠标,都不会显示任何文本。因为我们已经子类化QApplication,事件在到达QApplication的事件过滤器之前,会先到达QApplication的notify()函数,我们已经在子类化的MyApplication中屏蔽了MouseButtonPress、MouseButtonRelease事件。所以为MyApplication对象注册的事件过滤器不起作用。程序运行界面为: