Qt有很多事件,比如,键盘事件,大小改变的事件,鼠标事件,位置移动的事件等等。
怎么选择,一般有两种方法:
一、所有事件对应一个事件处理函数,在这个事件处理函数中用很大一个分支语句进行选择,如win32 API的WndProc()函数。
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,LPARAM lParam)
二、使用switch语句,选择message参数的类型进行处理
switch( message )
{
case WM_PAINT:
//..........
break;
case WM_DESTROY:
//..........
break;
}
三、每一种事件对应一个事件处理函数。Qt就是使用的这么一种机制:
mouseEvent()
keyPressEvent()
..........
总结:
Qt 的事件处理,实际上是有五个层次:
1. 重写 paintEvent()、mousePressEvent() 等事件处理函数。这是最普通、最简单的形式,同时功能也最简单。
2. 重写 event() 函数。event() 函数是所有对象的事件入口,QObject 和 QWidget中的实现,默认是把事件传递给特定的事件处理函数。
3. 在特定对象上面安装事件过滤器。该过滤器仅过滤该对象接收到的事件。
4. 在 QCoreApplication::instance() 上面安装事件过滤器。该过滤器将过滤所有对象的所有事件,因此和 notify() 函数一样强大,但是它更灵活,因为可以安装多个过滤器。全局的事件过滤器可以看到 disabled 组件上面发出的鼠标事件。全局过滤器有一个问题:只能用在主线程。
5. 重写 QCoreApplication::notify() 函数。这是最强大的,和全局事件过滤器一样提供完全控制,并且不受线程的限制。但是全局范围内只能有一个被使用(因为QCoreApplication 是单例的)。
下面是个事件先后调用顺序测试代码:
#include <QtWidgets/QApplication> #include <QtWidgets> class Label : public QWidget { public: Label() { installEventFilter(this); } bool eventFilter(QObject *watched, QEvent *e) { if (watched == this) { if (e->type() == QEvent::MouseButtonPress) { qDebug()<<"eventFilter"; } } return false; } protected: void mousePressEvent(QMouseEvent *) { qDebug()<<"mousePressEvent"; } bool event(QEvent *e) { if (e->type() == QEvent::MouseButtonPress) { qDebug()<<"event"; } return QWidget::event(e); } }; class EvenFilter : public QObject { public: EvenFilter(QObject *watched, QObject *parent = 0) : QObject(parent), m_watched(watched) { } bool evenFilter(QObject *watched, QEvent *e) { if (watched == m_watched) { if (e->type() == QEvent::MouseButtonPress) { qDebug()<<"QApplication::eventFilter"; } } return false; } private: QObject *m_watched; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Label label; a.installEventFilter(new EvenFilter(&label, &label)); label.show(); return a.exec(); }