Qt事件

1  简介

参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=31

参考资料:《Qt教程.docx》

本文主要介绍Qt的事件。

2  事件

(1)事件(event)

事件由系统或Qt本身在不同时刻发生的,例如按下鼠标、敲下键盘。

Qt程序需要在main()函数创建一个QApplication对象,然后调用它的exec()函数。这个函数就是开始Qt的事件循环,在执行exec()函数之后,程序将进入事件循环来监听应用程序的事件。但事件发生时,Qt将创建

一个事件对象,Qt中所有事件类都继承QEvent。在事件对象创建完毕后,将这个事件对象传递给QObject的event函数。

event()函数并不直接处理事件,而是按照事件对象的类型分派给特定的事件处理函数(event handler)。

(2)事件处理函数

在所有组件的父类QWidget中,定义了很多事件处理的回调函数,这些函数都是 protected virtual 的,也就是说,我们可以在子类中重新实现这些函数。

    

(3)测试

测试说明:创建一个QLabel,用于显示鼠标按下、释放、移动时的坐标,主要是为了测试鼠标按下、释放、移动这三个事件。

创建一个带ui的QWidget工程:

其中,mylabel是自定义的label,我们重写其鼠标事件:

mylabel.h中的代码如下:

 1 #ifndef MYLABEL_H
 2 #define MYLABEL_H
 3 
 4 #include <QWidget>
 5 #include <QLabel>
 6 
 7 class mylabel : public QLabel
 8 {
 9     Q_OBJECT
10 public:
11     explicit mylabel(QWidget *parent = nullptr);
12 
13 protected:
14     //事件处理函数
15     void mousePressEvent(QMouseEvent *ev);
16     void mouseReleaseEvent(QMouseEvent *ev);
17     void mouseMoveEvent(QMouseEvent *ev);
18 
19 signals:
20 
21 public slots:
22 };
23 
24 #endif // MYLABEL_H
View Code

mylabel.cpp中的代码如下:

 1 #include "mylabel.h"
 2 #include <QMouseEvent>
 3 #include <QString>
 4 
 5 mylabel::mylabel(QWidget *parent) : QLabel(parent)
 6 {
 7     this->setMouseTracking(true);
 8 }
 9 
10 void mylabel::mousePressEvent(QMouseEvent *ev)
11 {
12     QString text = QString("<center><h1>Mouse press:: (%1, %2)</h1></center>").arg(ev->x()).arg(ev->y());
13     this->setText(text);
14 }
15 
16 void mylabel::mouseReleaseEvent(QMouseEvent *ev)
17 {
18     QString text = QString("<center><h1>Mouse release:: (%1, %2)</h1></center>").arg(ev->x()).arg(ev->y());
19     this->setText(text);
20 }
21 
22 void mylabel::mouseMoveEvent(QMouseEvent *ev)
23 {
24     QString text = QString("<center><h1>Mouse move:: (%1, %2)</h1></center>").arg(ev->x()).arg(ev->y());
25     this->setText(text);
26 }
View Code

上述代码中使用了QWidge的mouseTracking属性,该属性用于设置是否追踪鼠标。只有鼠标被追踪时,mouseMoveEvent()才会发出。如果mouseTracking false(默认即是),组件在至少一次鼠标点击之后,才能够被追踪,也就是能够发出mouseMoveEvent()事件。如果mouseTracking true,则mouseMoveEvent()直接可以被发出。

将ui中的label提升为我们自定义的label。运行进行测试:

3  event()函数

(1)介绍

事件对象创建完毕后,Qt 将这个事件对象传递给QObject的event()函数。event()函数并不直接处理事件,而是将这些事件对象按照它们不同的类型,分发给不同的事件处理器(event handler)。

event()函数主要用于事件的分发。

如果你希望在事件分发之前做一些操作,可以重写这个event()函数。

函数原型:virtual bool event(QEvent *event);

返回值说明:如果传入的事件已被识别并处理,则需要返回true,否则返回false。如果返回值是true,那么Qt会认为这个事件已经处理完毕,不再将这个事件发送给其它对象,而是会继续处理事件队列中的下一个事件。

(2)测试

功能:在event函数中判断主窗口的鼠标移动事件,并将鼠标所在的坐标在QLabel中显示出来。

工程文件有:

 在widget.h中声明event函数:

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 protected:
19     //事件分发
20     bool event(QEvent *event);
21 
22 private:
23     Ui::Widget *ui;
24 };
25 
26 #endif // WIDGET_H
View Code

在widget.cpp中实现event函数:

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include <QEvent>
 4 #include <QLabel>
 5 #include <QString>
 6 #include <QMouseEvent>
 7 
 8 Widget::Widget(QWidget *parent) :
 9     QWidget(parent),
10     ui(new Ui::Widget)
11 {
12     ui->setupUi(this);
13     this->setMouseTracking(true);
14 }
15 
16 bool Widget::event(QEvent *event)
17 {
18     //判断事件是否是鼠标移动
19     if (event->type() == QEvent::MouseMove) {
20         QMouseEvent *ent = static_cast<QMouseEvent *>(event);
21         QString text = QString("<center><h1>Mouse move(%1, %2)</h1></center>").arg(ent->x()).arg(ent->y());
22         ui->label->setText(text);
23         //返回true,事件停止传播
24         return true;
25     } else{
26         //其它事件继续传播
27         return QWidget::event(event);
28     }
29 }
30 
31 Widget::~Widget()
32 {
33     delete ui;
34 }
View Code

运行测试:

(3)总结

event()函数中实际是通过事件处理器来响应一个具体的事件。这相当于event()函数将具体事件的处理“委托”给具体的事件处理器。而这些事件处理器是 protected virtual 的,因此,我们重写了某一个事件处理

器,即可让Qt 调用我们自己实现的版本。

event()是一个集中处理不同类型的事件的地方。如果你不想重写一大堆事件处理器,就可以重写这个event()函数,通过QEvent::type()判断不同的事件。

4  事件过滤器

(1)介绍

有时候对象需要查看、甚至要拦截发送到另外对象的事件,需要用到事件过滤器。事件过滤器与event()、事件处理器的关系如下:

事件过滤器,可以理解成一种过滤代码,它会检查接收到的事件,如果这个事件是我们感兴趣的类型,就进行我们自己的处理;如果不是,就继续转发。

函数原型:virtual bool eventFilter(QObject *watched, QEvent *event);

事件过滤器会检查接收到的事件,如果这个事件是我们感兴趣的类型,就自己处理,否则继续转发。返回值是一个bool类型,如果你想将参数 event 过滤出来,比如,不想让它继续转发,就返回 true,否则返回 false。

(2)测试

功能:创建一个事件过滤器,过滤出label标签中的鼠标移动事件并进行处理。

工程代码:

widget.h中添加eventFilter()函数声明:

 1 #ifndef WIDGET_H
 2 #define WIDGET_H
 3 
 4 #include <QWidget>
 5 
 6 namespace Ui {
 7 class Widget;
 8 }
 9 
10 class Widget : public QWidget
11 {
12     Q_OBJECT
13 
14 public:
15     explicit Widget(QWidget *parent = 0);
16     ~Widget();
17 
18 protected:
19     //事件过滤器
20     bool eventFilter(QObject *watched, QEvent *event);
21 
22 private:
23     Ui::Widget *ui;
24 };
25 
26 #endif // WIDGET_H
View Code

widget.cpp中添加实现eventFileter()函数,并过滤出Label对象的鼠标移动事件。

 1 #include "widget.h"
 2 #include "ui_widget.h"
 3 #include <QLabel>
 4 #include <QMouseEvent>
 5 #include <QEvent>
 6 #include <QString>
 7 
 8 Widget::Widget(QWidget *parent) :
 9     QWidget(parent),
10     ui(new Ui::Widget)
11 {
12     ui->setupUi(this);
13     //安装过滤器
14     ui->label->installEventFilter(this);
15     ui->label->setMouseTracking(true);
16 }
17 
18 Widget::~Widget()
19 {
20     delete ui;
21 }
22 
23 bool Widget::eventFilter(QObject *watched, QEvent *event)
24 {
25     //观察对象为label
26     if (watched == ui->label) {
27         QMouseEvent *ent = static_cast<QMouseEvent *>(event);
28         //判断鼠标移动事件
29         if (event->type() == QEvent::MouseMove) {
30             QString text = QString("<center><h1>mouse move:(%1, %2)</h1></center>").arg(ent->x()).arg(ent->y());
31             ui->label->setText(text);
32             return true;
33         }
34     }
35     //继续传递事件
36     return QWidget::eventFilter(watched, event);
37 }
View Code

运行测试:

 

posted @ 2020-07-01 23:46  zhengcixi  阅读(563)  评论(0编辑  收藏  举报
回到顶部