• 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

    运行测试:

  • 相关阅读:
    实现在Android本地视频播放器开发
    敏捷开发的4个中心思想
    PHP如何大幅度提升运行效率? 把它编译成机器码!
    卸载Oracle数据库(有图有真相)
    宁波理工邀请赛 c zoj3185解题报告
    FRG图像文件格式的压缩质量
    另类的文件夹加密(批处理实现)
    代码详查中的自尊心
    [C# 网络编程系列]专题十:实现简单的邮件收发器
    php中获得客户端,服务器ip
  • 原文地址:https://www.cnblogs.com/mrlayfolk/p/13222382.html
Copyright © 2020-2023  润新知