Qt 鼠标按下移动释放事件

文章目录

  • [1 通过自定义控件实现](#1 通过自定义控件实现)
    • [1.1 鼠标跟踪](#1.1 鼠标跟踪)
  • [2 鼠标事件移动标签](#2 鼠标事件移动标签)

QEvent::MouseButtonPress

​ 鼠标按下时,触发该事件,它对应的子类是QMouseEvent

QEvent::MouseMove

​ 鼠标移动时,触发该事件,它对应的子类是QMouseEvent

QEvent::MouseButtonRelease

​ 鼠标释放时,触发该事件,它对应的子类是QMouseEvent

1 通过自定义控件实现

自定义一个标签控件LabelX,让它继承自QLabel,然后重写父类的mousePressEventmouseReleaseEventmouseMoveEvent

代码如下:

c++ 复制代码
// 在LabelX.h 中
#ifndef LABELX_H
#define LABELX_H

#include <QDebug>
#include <QLabel>
#include <QMouseEvent>

class LabelX : public QLabel {
    Q_OBJECT
public:
    explicit LabelX(QWidget *parent = nullptr);

protected:
    // 重写父类的方法
    void enterEvent(QEnterEvent *event);
    void leaveEvent(QEvent *event);

    // 按下,移动,释放事件
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);

signals:
};

#endif  // LABELX_H


// 在LabelX.cpp 中
#include "labelx.h"

LabelX::LabelX(QWidget *parent) : QLabel{parent} {
    // 实现鼠标的跟踪
    this->setMouseTracking(true);  // 默认false
}

static int cnt = 1;

void LabelX::enterEvent(QEnterEvent *event) {
    Q_UNUSED(event);
    // qDebug() << "enterEvent: " << cnt++;
    this->setText(QString("enterEvent: %1").arg(cnt++));
}

void LabelX::leaveEvent(QEvent *event) {
    Q_UNUSED(event);
    // qDebug() << "leaveEvent: " << cnt++;
    this->setText(QString("leaveEvent: %1").arg(cnt++));
}

void LabelX::mousePressEvent(QMouseEvent *event) {
    // qDebug() << "mousePressEvent" << event->button() << event->pos()
    //          << event->globalPosition();
    if (event->button() == Qt::LeftButton) {
        qDebug() << "左键按下:"
                 << "x= " << event->x() << "y= " << event->y();
    }
}

void LabelX::mouseReleaseEvent(QMouseEvent *event) {
    // qDebug() << "mouseReleaseEvent" << event->button() << event->pos()
    //          << event->globalPosition();
    if (event->button() == Qt::LeftButton) {
        qDebug() << "左键释放:"
                 << "x= " << event->x() << "y= " << event->y();
    }
}

void LabelX::mouseMoveEvent(QMouseEvent *event) {
    qDebug() << "mouseMoveEvent" << event->buttons() << event->pos()
             << event->globalPosition();
    if (event->buttons() & Qt::LeftButton) {
        qDebug() << "左键释放:"
                 << "x= " << event->x() << "y= " << event->y();
    }
}

1.1 鼠标跟踪

以上,需要鼠标保持按下的状态下,系统才会调用mouseMoveEvent,实际工作中往往有这么一种需求:

鼠标悬浮在控件上,而不是按下,就触发mouseMoveEvent事件,这怎么实现呢?

答案:设置鼠标跟踪,默认情况下鼠标跟踪是关闭的,需要开启

首先,来到LabelX.cpp中,设置标签使能鼠标跟踪,如下:

c++ 复制代码
LabelX::LabelX(QWidget *parent) : QLabel{parent} {
    // 实现鼠标的跟踪
    this->setMouseTracking(true);  // 默认false
}

2 鼠标事件移动标签

C++ 复制代码
// 在press_move_release_widget.h中
#ifndef PRESSMOVERELEASEWIDGET_H
#define PRESSMOVERELEASEWIDGET_H

#include <QDebug>
#include <QEvent>
#include <QLabel>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QWidget>

#include "labelx.h"

class PressMoveReleaseWidget : public QWidget {
    Q_OBJECT
public:
    explicit PressMoveReleaseWidget(QWidget *parent = nullptr);

private:
    QLabel *lbl;
    QWidget *widget;

    QPoint pressPos;  // 鼠标按下的位置
    QPoint wndPos;    // 标签的位置 (左上角的点 top-left)

protected:
    bool eventFilter(QObject *obj, QEvent *event);

signals:
};

#endif  // PRESSMOVERELEASEWIDGET_H


// 在press_move_release_widget.cpp中
#include "press_move_release_widget.h"

PressMoveReleaseWidget::PressMoveReleaseWidget(QWidget *parent)
    : QWidget{parent} {
    QVBoxLayout *verticalLayout = new QVBoxLayout(this);
    verticalLayout->setSpacing(0);
    verticalLayout->setContentsMargins(0, 0, 0, 0);

    // 添加一个自定义控件
    LabelX *lblx = new LabelX(this);
    lblx->setText("鼠标按下/移动/释放");
    lblx->setFrameShape(QFrame::Box);
    lblx->setFixedHeight(50);
    lblx->setAlignment(Qt::AlignCenter);
    lblx->setStyleSheet(
        "background-color: blue; color: white; font-size: 25px");
    verticalLayout->addWidget(lblx);

    // 添加一个标准控件
    widget = new QWidget(this);
    lbl = new QLabel(widget);
    lbl->setText("");
    lbl->setFrameShape(QFrame::Box);
    lbl->setFixedSize(100, 100);
    lbl->setStyleSheet("background-color: red;");
    verticalLayout->addWidget(widget);

    // 安装事件过滤器
    lbl->installEventFilter(this);
}

bool PressMoveReleaseWidget::eventFilter(QObject *obj, QEvent *event) {
    if (obj != lbl) {
        return QWidget::eventFilter(obj, event);
    }

    if (event->type() == QEvent::MouseButtonPress) {
        qDebug() << "MouseButtonPress";
        // 记录鼠标按下的位置,当前标签的位置
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        pressPos = mouseEvent->globalPos();
        // 标签的位置 (左上角的点 top-left)
        wndPos = lbl->pos();
        qDebug() << wndPos;
    } else if (event->type() == QEvent::MouseMove) {
        qDebug() << "MouseMove";
        QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
        // 标签的位置 + (鼠标当前的位置 - 按下鼠标的位置)
        // 他们两之差就是鼠标移动的距离
        QPoint dstPos = wndPos + (mouseEvent->globalPos() - pressPos);
        lbl->move(dstPos);

        // 超出了最左边
        if (lbl->pos().x() < 0) {
            lbl->move(0, dstPos.y());
        }

        // 超出了最右边
        if (lbl->pos().x() > widget->width() - lbl->width()) {
            lbl->move(widget->width() - lbl->width(), dstPos.y());
        }

        // 超出了最上边
        if (lbl->pos().y() < 0) {
            lbl->move(dstPos.x(), 0);
        }

        // 超出了最下边
        if (lbl->pos().y() > widget->height() - lbl->height()) {
            lbl->move(dstPos.x(), widget->height() - lbl->height());
        }

    } else if (event->type() == QEvent::MouseButtonRelease) {
        qDebug() << "MouseButtonRelease";
    }
}
相关推荐
Antonio9156 分钟前
【网络编程】WebSocket 实现简易Web多人聊天室
前端·网络·c++·websocket
深海潜水员9 分钟前
【Unity】背包系统 + 物品管理窗口 (上)
开发语言·vscode·游戏·unity·c#·游戏引擎
德育处主任Pro1 小时前
p5.js 用 beginGeometry () 和 endGeometry () 打造自定义 3D 模型
开发语言·javascript·3d
kyranhan1 小时前
C#程序本地运行正常,通过网络下载报错:FileLoadException:“未能加载文件或程序集“xxx.dll”或它的某一个依赖项。
开发语言·c#·wpf
清朝牢弟2 小时前
Ubuntu系统VScode实现opencv(c++)图像放缩与插值
c++·vscode·opencv·ubuntu·计算机视觉
呆瑜nuage2 小时前
list的使用和模拟
c++·list
tomato092 小时前
Codeforces Round 1040 (Div. 2)(补题)
c++
zhangzhangkeji2 小时前
QT6 源,十章绘图(2)画刷 QBrush:刷子只涉及填充颜色,线型,填充图片,以及变换矩阵这几个属性,附源代码带注释。
qt
好好先森&2 小时前
C语言:模块化编程
c语言·c++·windows
重生之我是Java开发战士2 小时前
【C语言】结构体详解
c语言·开发语言