【Qt】系统相关(二)鼠标事件的处理,鼠标的按下,释放,双击,移动,滚轮滚动事件的处理

小编个人主页详情<---请点击
小编个人gitee代码仓库<---请点击
Qt系列专栏<---请点击
倘若命中无此运,孤身亦可登昆仑,送给屏幕面前的读者朋友们和小编自己!


目录


前言

【Qt】系统相关(一)内容简介,事件概念,事件的处理------书接上文 详情请点击<------,本文会在上文的基础上进行讲解,所以对上文不了解的读者友友请点击前方的蓝字链接进行学习

本文由小编为大家介绍------【Qt】系统相关(二)鼠标事件的处理,鼠标的按下,释放,双击,移动,滚轮滚动事件的处理


一、鼠标事件的处理

通过事件获取鼠标点击的位置

  1. 我们想要通过事件来获取鼠标点击的位置该如何做呢?我们需要对mousePressEvent这个函数在派生类中进行重写,所以接下来我们创建一个项目名为mousePressEvent,基类为QWidget,派生类为Widget的项目,接下来我们点击ui文件,进入Qt Designer

  2. 所以此时我们拖拽左侧红框内的控件,然后调整成上图界面即可,接下来我们选中标签控件,将右侧的边框属性frameShape选中为box,此时标签控件的边框比较明显,这样可以清晰的观察鼠标是否点击到了标签控件,objectName保持不变

  3. 那么在右上角我们看到当前界面上的label控件的类型还是QLabel,我们需要重写mousePressEvent,那么就需要创建派生类Label继承自基类QLabel,然后在派生类Label中将mousePressEvent进行重写,接下来我们再将界面上的label控件的类型QLabel提升为Label,这些细节小编在上一篇文章中都进行了详尽的讲解了 详情请点击<------

  4. 接下来我们先需要创建QLabel的派生类Label,所以鼠标左上角点击文件,选择新建文件或项目,接下来在左侧的文件和类中选择C++,然后继续选择C++ Class,接下来派生类输入Label,基类输入QLabel,然后勾选上Include QWidget,还有信号槽Add Q_OBJECT,虽然我们不使用,但是包含一下也没有坏处

  5. 此时就可以让Qt帮我们生成继承自QLabel的派生类Label,如上关于这个类的声明相关的label.h头文件就有了,关于这个类的label.cpp源文件就有了

cpp 复制代码
#ifndef LABEL_H
#define LABEL_H

#include <QWidget>
#include <QLabel>


class Label : public QLabel
{
    Q_OBJECT
public:
    Label(QWidget* parent);
    
public:
    void mousePressEvent(QMouseEvent* event);
    
};

#endif // LABEL_H
  1. 那么在.h头文件中,我们加上基类QLabel的头文件#include <QLabel>,然后在Label的构造函数的形参中加上QWidget* parent,主要是为了使用对象树机制,将父元素传参给基类QLabel,然后使用基类的对象树机制将派生类一并挂接到对象树中指定的的父元素下
  2. 由于我们想要在派生类Label中重写基类QLabel的虚函数,所以我们声明鼠标按下的事件处理函数mousePressEvent,但是要注意,这里我们在进行声明的时候一定要注意派生类Label中的函数名和参数的顺序,个数,类型要和基类QLabel中的函数一致,这里小编教大家一招,为了防止拼写错误,我们可以去Qt的官方文档中去找这个mousePressEvent,然后对于这个mousePressEvent的声明我们直接复制粘贴到我们的代码中进行声明即可
cpp 复制代码
#include "label.h"
#include <QMouseEvent>
#include <QDebug>

Label::Label(QWidget* parent)
    : QLabel(parent)
{

}

void Label::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "(" << event->x() << ", " << event->y() << ")\n";

}
  1. 首先我们包好QMouseEvent以及qLabel对应要使用的头文件,所以此时我们在派生类Label的.cpp文件中对于构造函数的参数设置为QWidget* parent,所以此时在初始化列表中传入父元素parent调用基类QLabel的构造函数,将派生类Label设置进对象树中父元素parent下即可
  2. 接下来就要实现mousePressEvent事件处理函数了,其实在mousePressEvent函数的类型为QMouseEvent的形参mouse中,其实就有触发这次事件的关于鼠标的相关属性,换句话来说,我们想要的鼠标点击的位置坐标就在类型为QMouseEvent的形参mouse中,所以此时我们直接使用x和y函数就可以进行获取,接下来我们使用qDebug()将鼠标点击的位置坐标打印即可
  3. 所以此时我们点击ui文件,进入Qt Designer,然后右击界面上的QLabel标签,然后选择提升为
  4. 所以上图左侧此时我们添加提升的类的名称为Label,头文件为label.h,然后点击添加,接下来上图中央,我们选中Label,然后点击提升,特别注意的是,这里我们添加提升的类的名称和头文件的时候,一定要确保我们添加的提升的类的名称和头文件和我们自定义的类的名称和头文件要匹配
  5. 此时当我们点击了提升之后,如上图,label对象原本为基类QLabel,此时就被类型提升为了派生类Label,所以此时通过提升为这样的方式,我们可以把Qt Designer中拖拽上去的控件类型转换为自定义的控件类型

运行结果如下

  1. 所以此时小编从Label控件的右下角开始向左上角逐渐点击,可以看到,确实鼠标点击的位置坐标被打印了出来
  2. 但是随着小编从Label控件的右下角开始向左上角逐渐点击,位置坐标的横坐标x和纵坐标y也在不断的减小,换句话来讲,位置坐标在不断的逼近原点,这里的原点就是Label控件的左上角
  1. 位置坐标是基于原点作为参考系的,那么也就是说原点位置的不同,位置坐标也会不同
    (1)关于原点,在第八点Qt坐标系的认识中进行的讲解,详情请点击<------
    (2)关于位置,在第一点QWidget的geometry中进行的讲解,详情请点击<------
cpp 复制代码
#include "label.h"
#include <QMouseEvent>
#include <QDebug>

Label::Label(QWidget* parent)
    : QLabel(parent)
{

}

void Label::mousePressEvent(QMouseEvent *event)
{
    qDebug() << "(" << event->x() << ", " << event->y() << ")";

    qDebug() << "(" << event->globalX() << ", " << event->globalY() << ")\n";
}
  1. 所以如果今天这个原点是屏幕显示器的左上角,那么也就是说位置坐标也会和之前位置坐标是Label控件的左上角的时候不同,所以接下来我们使用globalX和globalY获取原点为屏幕左上角的时候的横坐标x和纵坐标y,并且使用qDebug()打印出来,为了便于对比,我们把以Label控件左上角为原点的打印日志信息的换行去掉

运行结果如下

  1. 所以此时小编从Label控件的右下角开始向左上角逐渐点击,可以看到,确实鼠标点击的位置坐标被打印了出来
  2. 这里我们观察打印的位置坐标,对于原点是Label控件左上角的位置坐标较小,对于原点是屏幕左上角的位置坐标较大,所以对于采用不同原点为参考系的位置坐标是不同的
cpp 复制代码
#include "label.h"
#include <QMouseEvent>
#include <QDebug>

Label::Label(QWidget* parent)
    : QLabel(parent)
{

}

void Label::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "按下左键";
    else if(event->button() == Qt::MidButton)
        qDebug() << "按下滚轮";
    else if(event->button() == Qt::RightButton)
        qDebug() << "按下右键";


    qDebug() << "(" << event->x() << ", " << event->y() << ")";
    
    qDebug() << "(" << event->globalX() << ", " << event->globalY() << ")\n";
}

判断鼠标究竟是哪个按键进行点击

  1. 此时我们思考一下,鼠标点击,此时我们是使用的鼠标左键进行的点击,那么使用鼠标右键,鼠标滚轮进行点击是否可以呢?可以的
cpp 复制代码
enum MouseButton {
    NoButton         = 0x00000000,
    LeftButton       = 0x00000001,  // 鼠标左键
    RightButton      = 0x00000002,  // 鼠标右键
    MidButton        = 0x00000004,  // 鼠标滚轮
    MiddleButton     = MidButton,
    BackButton       = 0x00000008,  // 后退键
    XButton1         = BackButton,
    ExtraButton1     = XButton1,
    ForwardButton    = 0x00000010,  // 前进键
    XButton2         = ForwardButton,
    ExtraButton2     = ForwardButton,
    TaskButton       = 0x00000020,
    ExtraButton3     = TaskButton,
    ExtraButton4     = 0x00000040,
    ExtraButton5     = 0x00000080,
    ExtraButton6     = 0x00000100,
    ExtraButton7     = 0x00000200,
    ExtraButton8     = 0x00000400,
    ExtraButton9     = 0x00000800,
    ExtraButton10    = 0x00001000,
    ExtraButton11    = 0x00002000,
    ExtraButton12    = 0x00004000,
    ExtraButton13    = 0x00008000,
    ExtraButton14    = 0x00010000,
    ExtraButton15    = 0x00020000,
    ExtraButton16    = 0x00040000,
    ExtraButton17    = 0x00080000,
    ExtraButton18    = 0x00100000,
    ExtraButton19    = 0x00200000,
    ExtraButton20    = 0x00400000,
    ExtraButton21    = 0x00800000,
    ExtraButton22    = 0x01000000,
    ExtraButton23    = 0x02000000,
    ExtraButton24    = 0x04000000,
    AllButtons       = 0x07ffffff,
    MaxMouseButton   = ExtraButton24,
    // 4 high-order bits remain available for future use (0x08000000 through 0x40000000).
    MouseButtonMask  = 0xffffffff
};
  1. 所以我们使用类型为QMouseEvent类型的对象event中的方法button获取当前鼠标是按下的哪一个键,如上Qt对于鼠标按下的键都进行了如上详尽的枚举,然后进行if语句的判断即可,如果是左键,那么就打印左键日志,如果按下的是滚轮,那么就打印滚轮日志,如果按下的是右键,那么就打印右键日志

运行结果如下

  1. 所以此时小编依次按下鼠标左键,滚轮,右键,此时鼠标事件被触发,执行到了鼠标按压的事件处理函数mousePressEvent,那么对应按键的日志就被打印了
  2. 注意,鼠标的滚轮进行滚动不算鼠标按下,而是属于鼠标滚动,所以自然也就不会触发鼠标按下事件,进而这里的鼠标按下mousePressEvent事件处理函数也就不会执行了
  1. 小编使用的鼠标是小米无线蓝牙双模鼠标2,这款鼠标其实挺好用的,静音,适合在图书馆使用,不影响他人,那么我们从上图可以看到,这款鼠标除了有左键,滚轮,右键,还有两个侧键,也就是对应前进键和后退键,同样的前进键和后退键也可以触发鼠标点击mousePressEvent这个事件处理函数
cpp 复制代码
#include "label.h"
#include <QMouseEvent>
#include <QDebug>

Label::Label(QWidget* parent)
    : QLabel(parent)
{

}

void Label::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "按下左键";
    else if(event->button() == Qt::MidButton)
        qDebug() << "按下滚轮";
    else if(event->button() == Qt::RightButton)
        qDebug() << "按下右键";
    else if(event->button() == Qt::ForwardButton)
        qDebug() << "按下前进键";
    else if(event->button() == Qt::BackButton)
        qDebug() << "按下后退键";

    qDebug() << "(" << event->x() << ", " << event->y() << ")";

    qDebug() << "(" << event->globalX() << ", " << event->globalY() << ")\n";
}
  1. 所以此时我们继续在鼠标按下事件对应的事件处理函数mousePressEvent中,通过button拿到鼠标按下的按键,使用if语句对鼠标按下的按键进行判断,如果是前进键,那么就打印前进键的日志,如果是后退键,那么就打印后退键的日志

运行结果如下

  1. 所以此时小编按下前进键,按下后退键,都可以触发鼠标按下事件,进而就会执行对应的事件处理函数mousePressEvent进行对应前进键和后退键日志的打印
  2. 注意,一定要确保鼠标的范围是出于Label控件内,此时触发的鼠标事件,才可以顺利的执行到我们在派生类Label中重写的事件处理函数mousePressEvent
  1. 但是还有的鼠标,还有更多的按钮,例如罗技G502鼠标,这款鼠标的特点就是按键非常多,多达11个,除了有左键,滚轮,右键,前进键,后退键之外,还有剩下的6个按键,那么关于这6个的按键究竟是否可以触发鼠标按下事件,进而执行到对应鼠标按下事件的事件处理函数mousePressEvent就不确定了,为什么呢?
  2. 因为这6个按钮可以支持用户进行diy自定义鼠标按键,也就是说可以将这6个鼠标按键通过罗技G502鼠标的驱动程序,将这6个鼠标按键替换成任意的键盘组合键,此时按下这6个鼠标按键就相当于按下了键盘的组合键,此时关于这6个鼠标按键的按下我们就无法将其定义为鼠标按键的按下了,而是将其定义为键盘上组合键的按下,所以此时自然无法触发鼠标按下事件,自然也就无法执行到对应鼠标按下事件的事件处理函数mousePressEvent了

判断鼠标究竟是哪一个按键进行的释放

  1. 我们可以通过mouseReleaseEvent来获取鼠标的释放事件,需要注意的是,之前我们通过mousePressEvent获取的是鼠标的按下事件,是通过鼠标的按下事件来获取的究竟是鼠标的哪一个按键进行的按下,所以接下来我们期望通过鼠标的释放来获取究竟是鼠标的哪一个按键进行的释放
cpp 复制代码
#ifndef LABEL_H
#define LABEL_H

#include <QWidget>
#include <QLabel>


class Label : public QLabel
{
    Q_OBJECT
public:
    Label(QWidget* parent);

public:
    void mousePressEvent(QMouseEvent* event);

    void mouseReleaseEvent(QMouseEvent* event);

};

#endif // LABEL_H
  1. 所以此时我们继续在Label的.h头文件中,声明mouseReleaseEvent即可
cpp 复制代码
#include "label.h"
#include <QMouseEvent>
#include <QDebug>

Label::Label(QWidget* parent)
    : QLabel(parent)
{

}

void Label::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "按下左键";
    else if(event->button() == Qt::MidButton)
        qDebug() << "按下滚轮";
    else if(event->button() == Qt::RightButton)
        qDebug() << "按下右键";
    else if(event->button() == Qt::ForwardButton)
        qDebug() << "按下前进键";
    else if(event->button() == Qt::BackButton)
        qDebug() << "按下后退键";

//    qDebug() << "(" << event->x() << ", " << event->y() << ")";

//    qDebug() << "(" << event->globalX() << ", " << event->globalY() << ")\n";
}

void Label::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "释放左键";
    else if(event->button() == Qt::MidButton)
        qDebug() << "释放滚轮";
    else if(event->button() == Qt::RightButton)
        qDebug() << "释放右键";
    else if(event->button() == Qt::ForwardButton)
        qDebug() << "释放前进键";
    else if(event->button() == Qt::BackButton)
        qDebug() << "释放后退键";
}
  1. 接下来在Label的.cpp源文件中,我们先将鼠标按下事件对应的事件处理函数mousePressEvent中关于鼠标位置的打印注释掉,我们去实现一下鼠标释放事件对应的事件处理函数mouseReleaseEvent即可,实现方式同样很简单,依旧是使用button获取到当前鼠标释放的是哪一个按键,然后进行逐个的比对,接下来打印日志即可

运行结果如下

  1. 所以此时小编对于鼠标的各个按键进行按下,释放都可以正常触发对应的鼠标按下事件,鼠标释放事件,进而去执行对应的事件处理函数,进行日志的打印
  1. 所以此时我们来看,其实我们在信号槽部分,学到的clicked点击这样的信号,其实对于点击信号来讲,就相当于一次鼠标按下事件和一次鼠标释放事件

判断鼠标按键究竟是哪一个按键进行的双击

  1. 当鼠标双击的时候,会触发鼠标双击事件,进而就会执行对应的事件处理函数mouseDoubleClickEvent,所以此时我们就可以在mouseDoubleClickEvent中判断鼠标按键究竟是哪一个按键进行的双击,同样的Qt可以保证在Qt程序中的鼠标双击的事件间隔会跟随系统,也就意味着用户在Qt的程序中进行双击和普通进行双击在体验上并没有差异
cpp 复制代码
#ifndef LABEL_H
#define LABEL_H

#include <QWidget>
#include <QLabel>


class Label : public QLabel
{
    Q_OBJECT
public:
    Label(QWidget* parent);

public:
    void mousePressEvent(QMouseEvent* event);

    void mouseReleaseEvent(QMouseEvent* event);

    void mouseDoubleClickEvent(QMouseEvent* event);

};

#endif // LABEL_H
  1. 所以此时我们继续在Label的.h头文件中,声明mouseDoubleClickEvent即可
cpp 复制代码
#include "label.h"
#include <QMouseEvent>
#include <QDebug>

Label::Label(QWidget* parent)
    : QLabel(parent)
{

}

void Label::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "按下左键";
    else if(event->button() == Qt::MidButton)
        qDebug() << "按下滚轮";
    else if(event->button() == Qt::RightButton)
        qDebug() << "按下右键";
    else if(event->button() == Qt::ForwardButton)
        qDebug() << "按下前进键";
    else if(event->button() == Qt::BackButton)
        qDebug() << "按下后退键";

//    qDebug() << "(" << event->x() << ", " << event->y() << ")";

//    qDebug() << "(" << event->globalX() << ", " << event->globalY() << ")\n";
}

void Label::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "释放左键";
    else if(event->button() == Qt::MidButton)
        qDebug() << "释放滚轮";
    else if(event->button() == Qt::RightButton)
        qDebug() << "释放右键";
    else if(event->button() == Qt::ForwardButton)
        qDebug() << "释放前进键";
    else if(event->button() == Qt::BackButton)
        qDebug() << "释放后退键";
}

void Label::mouseDoubleClickEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        qDebug() << "双击左键";
    else if(event->button() == Qt::MidButton)
        qDebug() << "双击滚轮";
    else if(event->button() == Qt::RightButton)
        qDebug() << "双击右键";
    else if(event->button() == Qt::ForwardButton)
        qDebug() << "双击前进键";
    else if(event->button() == Qt::BackButton)
        qDebug() << "双击后退键";
}
  1. 接下来在Label的.cpp源文件中,我们去实现一下鼠标双击事件对应的事件处理函数mouseDoubleClickEvent即可,实现方式同样很简单,依旧是使用button获取到当前鼠标双击的是哪一个按键,然后进行逐个的比对,接下来打印日志即可

运行结果如下

  1. 这里有细节,如上,此时小编双击鼠标左键,当第二次按下鼠标左键的时候,才能够识别到是双击,而在此之前的鼠标左键按下和释放事件也被触发了,鼠标的一次按下和释放也就是一次点击,所以此时也就存在一个隐患了
  2. 比如我们在实际开发一些程序的时候,可能是鼠标单击有一些逻辑,鼠标双击有另外一些逻辑,所以如果我们没注意,此时鼠标双击操作就有可能就会触发鼠标单击的逻辑,此时就有可能会有bug,所以需要我们在开发的过程中格外注意

对鼠标移动的位置坐标进行打印

  1. 鼠标移动其实也会触发事件,进而就会执行到对应的事件处理函数mouseMoveEvent,所以此时我们想要将鼠标移动后的坐标获取并打印一下,那么在上面对于鼠标的按下,释放,双击事件的处理,重写鼠标的事件处理函数的操作,我们都是在自定义的Label控件中完成的,此时鼠标只有在Label控件的范围内进行动作的时候,才可以捕捉的到
  2. 同样的,我们也可以把重写鼠标的事件处理函数放到Widget中来完成,别忘了Widget派生类继承自基类QWidget,所以在派生类Widget中我们也可以对鼠标的事件处理函数进行重写,这样的话,鼠标动作就是相对于Widget控件这个窗口了,鼠标在整个窗口中进行的各种动作都可以获取的到了,所以接下来我们创建一个项目名为mouseMoveEvent,基类为QWidget,派生类为Widget的项目
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QMouseEvent>
#include <QDebug>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << "(" << event->x() << ", " << event->y() << ")";
}
  1. 所以接下来在鼠标移动的事件处理函数mouseMoveEvent中,我们使用x和y方法获取到鼠标移动后的横坐标x和纵坐标y,接下来使用qDebug()打印即可,这里我们需要声明QMouseEvent和qDebug()的头文件

运行结果如下

  1. 可是在Widget窗口中,小编不断的移动鼠标,此时并没有任何日志打印,也就意味着鼠标移动对应的事件处理函数mouseMoveEvent并没有被执行,换句话来讲鼠标移动事件并没有被触发,这是为什么呢?
  1. 其实鼠标移动不同于鼠标按下,那么我们随便移动一下鼠标,就会产生大量的鼠标移动事件,此时我们进行捕获事件的时候,尤其是我们在鼠标移动对应的事件处理函数mouseMoveEvent中进行了一些复杂逻辑的时候,此时程序的负担和消耗就很重,进而就会在降低程序的性能,对于此时的GUI程序就会给用户呈现出一种很卡顿的现象
  2. 所以Qt为了保证程序运行的流畅性,默认情况下不会对鼠标的移动进行追踪,也就是说鼠标的移动不会触发对应的事件处理函数mouseMoveEvent的执行,所以此时我们在Widget窗口上不断的移动鼠标,此时并不会有任何的日志进行打印,所以我们该如何做才可以让Qt追踪鼠标的移动呢?
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QMouseEvent>
#include <QDebug>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    
    this->setMouseTracking(true);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    qDebug() << "(" << event->x() << ", " << event->y() << ")";
}
  1. 所以此时就需要我们显示的告诉Qt,帮我们追踪鼠标的移动位置,那么我们该如何告诉呢?所以此时在Widget的构造函数中,上来我们就使用setMouseTracking,将是否追踪鼠标位置设置为true,表示此时追踪鼠标的移动位置,所以此时Qt就会帮我们自动最终鼠标的移动位置了,进而鼠标移动事件也就会触发,进而鼠标移动对应的事件处理函数mouseMoveEvent也就会被执行了,进而鼠标移动后的位置也就会被打印出来了

运行结果如下

  1. 所以此时在Widget窗口中,随着小编不断的移动鼠标,鼠标移动后的位置坐标也就不断的以日志的形式进行打印,也就意味着鼠标移动对应的事件处理函数mouseMoveEvent被执行了,即鼠标移动事件被触发,代表此时Qt帮我们追踪了鼠标的移动位置

获取鼠标滚轮滚动后的总像素值

  1. 鼠标上的滚轮进行滚动,那么Qt事件是否有对应的事件触发呢?其实是有的,鼠标上的滚轮进行滚动会触发滚动事件,进而就会执行对应的事件处理函数wheelEvent,那么在类型为QWheelEvent指针的形参event中,就可以调用delta方法来获取这次鼠标滚轮事件中,滚轮滚动了多远,滚动了多远的单位是像素值px,关于像素的讲解,在第八点,Qt坐标系的认识中的第13小点中进行的讲解,详情请点击<------
  2. 同样的,对于形参类型中的QWheelEvent是滚动事件,也就是继承自QEvent这个基类的派生类QWheelEvent,不同的场景下可以对应不同的事件派生类,所以接下来我们创建一个项目名为wheelEvent,基类为QWidget,派生类为Widget的项目
cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public slots:
    void wheelEvent(QWheelEvent *event);

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H
  1. 所以在Widget的.h头文件中,我们声明滚轮滚动事件对应的事件处理函数wheelEvent
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QWheelEvent>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::wheelEvent(QWheelEvent *event)
{
    qDebug() << event->delta();
}
  1. 在Widget的.cpp源文件中我们实现一下滚轮滚动事件对应的事件处理函数wheelEvent,所以此时我们调用delta获取这次事件鼠标滚轮滚动了多远,单位是像素,接下来使用qDebug()打印即可,这里我们需要声明QWheelEvent和qDebug()的头文件

运行结果如下

  1. 此时小编使用滚轮向上滚动,每次滚动一格,那么就触发一次滚轮滚动事件,进而就会执行wheelEvent,打印日志120,也就是说鼠标滚轮每次向上滚动,就会滚动120像素
  2. 同样的道理,小编将滚轮向下滚动,每次滚动一格,那么就触发一次滚轮滚动事件,进而就会执行wheelEvent,打印日志-120,也就是说鼠标滚轮每次向上滚动,就会滚动负的120像素
  3. 也就是说我们可以采用正数和负数来区分滚轮滚动的方向,所以如果滚轮是向上滚动,那么滚动的像素值就是正数,如果滚轮是向下滚动,那么滚动的像素值就是值就是负数
  1. 接下来小编再做一个实验,运行程序,将焦点聚焦在Qt Creator的代码编辑区域,此时小编滚动滚轮,无法打印日志,并不能触发Widget窗口的鼠标滚轮滚动事件,即没有执行wheelEvent
  2. 那么当小编点击Widget窗口,让焦点聚焦在Widget窗口上的时候,此时小编滚动滚轮,此时就可以打印日志,也就意味着触发了Widget窗口的鼠标滚轮滚动事件,即执行了wheelEvent
  3. 所以对于我们来讲,如果要想鼠标滚轮滚动事件被触发,需要确保焦点位于对应的控件或者窗口上,让对应的控件或窗口处于被激活状态 关于焦点,在第二点QWidget的focusPolicy属性中进行的讲解,详情请点击<------
cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

public slots:
    void wheelEvent(QWheelEvent *event);

private:
    Ui::Widget *ui;

    int total;
};
#endif // WIDGET_H
  1. 小编,小编,那么我们是否有手段得知,当前鼠标滚轮滚动事件触发后,鼠标滚轮滚动的总像素值吗?有方法,我们可以从QWheelEvent的detal方法中得知,每次触发滚轮滚动事件之后,滚轮滚动的像素值,这个像素值根据滚轮滚动的方向不同,有正有负
  2. 如果为正,那么表示向上滚动,如果为负,那么表示向下滚动,所以我们采用一个成员变量total将每次滚轮滚动事件触发之后对应滚动的像素值累加起来,就可以得知鼠标滚轮滚动的总像素值了,所以我们在Widget的私有成员变量中声明int整数类型的total变量
cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QWheelEvent>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
    , total(0)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::wheelEvent(QWheelEvent *event)
{
    total += event->delta();

    qDebug() << total;
}
  1. 接下来小编在Widget的.cpp源文件中,对于滚轮滚动事件对应的事件处理函数wheelEvent,所以此时我们调用delta获取这次事件鼠标滚轮滚动的像素值,将像素值累加到私有成员变量total中即可,然后使用qDebug()打印total的值,即打印的是鼠标滚轮滚动事件触发后鼠标滚轮滚动的总像素值

运行结果如下

  1. 此时小编将滚轮向上,向下滚动,就可以得出鼠标滚轮滚动事件触发后鼠标滚轮滚动的总像素值
  2. 提及鼠标滚轮的滚动操作,同样的,例如我们在一些编译器上,可以采用ctrl+滚轮滚动的方式,调整界面上文字的大小
  3. 那么在这里,我们也可以将我们获取到的鼠标滚轮滚动的总像素值和控件上显示的文字的字体字号进行一定程度的映射,进而我们就可以通过滚轮滚动来调整控件内显示文字的大小了,感兴趣的读者友友可以自行尝试一下

总结

以上就是今天的博客内容啦,希望对读者朋友们有帮助

水滴石穿,坚持就是胜利,读者朋友们可以点个关注

点赞收藏加关注,找到小编不迷路!

相关推荐
承渊政道1 小时前
【动态规划算法】(一文讲透二维费用的背包问题)
数据结构·c++·学习·算法·leetcode·动态规划·哈希算法
yqcoder1 小时前
JavaScript 深拷贝:如何彻底切断引用关联?
开发语言·前端·javascript
知识分享小能手1 小时前
R语言入门学习教程,从入门到精通,初识R语言(1)
开发语言·学习·r语言
2301_815279521 小时前
鸿蒙原生开发的“硬核通道”:ArkTS 与 C/C++ 高性能互操作全栈指南 —— FFI 机制深度解析与实战精要
c语言·c++·harmonyos
代码羊羊2 小时前
Rust 迭代器完全通俗易懂指南(零基础全覆盖)
java·开发语言·rust
MY_TEUCK9 小时前
【Java 后端】SpringBoot 登录认证与会话跟踪实战(JWT + Filter/Interceptor)
java·开发语言·spring boot
QQ24221997910 小时前
基于python+微信小程序的家教管理系统_mh3j9
开发语言·python·微信小程序
沐知全栈开发10 小时前
JavaScript 条件语句
开发语言
RSTJ_162510 小时前
PYTHON+AI LLM DAY THREETY-SEVEN
开发语言·人工智能·python