Qt 鼠标左键推拽界面

直接重写mouse的事件

代码实现:
button 返回 哪个按钮造成了此事件,buttons 返回 发生此事件时哪些按钮还处于按下状态

#include <QMouseEvent>

private:
	    // 记录坐标差值
    QPoint diff;
    QPoint now_pos;
    bool m_MouseDrag = false; // 一定要记得初始化为false

void Dialog::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton) {
    	m_MouseDrag = true;
                      // 鼠标在全局的位置     // 界面左上角在全局的位置
        this->diff = event->globalPos() - this->frameGeometry().topLeft();
        // 如果是通过界面里的某个部件,进行拖拽移动,获取界面左上角在全局的位置是比较麻烦的
        // 需要用其父类来获取,直接调用parent()函数得到是Object类型,没有frameGeometry成员函数
        // 需要强转为父类 ((QWidget *)this->parent())->frameGeometry.topLeft()
        // 这里只是以父类为 QWidget 为例
        return;
    }
    QDialog::mousePressEvent(event);
}

void Dialog::mouseMoveEvent(QMouseEvent *event)
{
    if(m_MouseDrag && event->buttons() == Qt::LeftButton) {
        QPoint now_pos = event->globalPos() - this->diff;
        this->move(now_pos);
        return;
    }
    QDialog::mouseMoveEvent(event);
}

void Dialog::mouseReleaseEvent(QMouseEvent *event)
{
    // 释放鼠标事件(左键)
    if(event->button() == Qt::LeftButton){
        m_MouseDrag = false;
        return;
    }
    QDialog::mouseReleaseEvent(event);
}

实现一个类

appinitdrag.h

#include <QObject>
#include <QMutex>
#include <QApplication>
#include <QWidget>
#include <QMouseEvent>

class AppInitDrag : public QObject
{
    Q_OBJECT
public:
    AppInitDrag();
    static AppInitDrag* GetInstance();
    void start();

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

private:
    static AppInitDrag *self;
};

appinitdrag.cpp

#include "appinitdrag.h"

AppInitDrag::AppInitDrag()
{

}
AppInitDrag *AppInitDrag::self = 0;
AppInitDrag *AppInitDrag::GetInstance()
{// 双重检查锁定机制(Double-Checked Locking)的单例模式
    if(self == nullptr) {
        // 避免多个线程同时通过锁定和创建实例
        QMutex mutex; // 用于实现互斥锁, 确保多线程环境下对 self 的访问是安全的
// QMutexLocker 是Qt提供的辅助类,它简化了对QMutex的使用,通过在其初始化时自动锁定和解锁互斥锁
        QMutexLocker locker(&mutex); // RAII 风格的锁定对象,能确保只有一个线程能够持有 mutex
        if(self == nullptr) {
            // 在锁定的情况下再次检查 self 是否为 nullptr,以防止多个线程同时通过第一次检查
            self = new AppInitDrag;
        }
    }
    return self;
}

void AppInitDrag::start()
{
/*
QApplication(通常简写为qApp)是Qt框架中的一个核心类,用于管理应用程序的控制流和全局设置。
它是Qt应用程序的主要入口点,并提供了一些基本的应用程序功能,包括事件处理、国际化支持、应用程序广播以及整个应用程序的全局设置
*/
//将 this 注册为事件过滤器,从而捕捉特定的鼠标事件
    qApp->installEventFilter(this); // 安装事件过滤器
}

// 使得具有 canMove 属性的 QWidget 窗口能够通过鼠标左键拖动来移动的功能
bool AppInitDrag::eventFilter(QObject *obj, QEvent *event)
{
    QWidget *w = (QWidget *)obj;
    if (!w->property("canMove").toBool()) {
        return QObject::eventFilter(obj, event);
    }

    static QPoint mousePoint;
    static bool mousePressed = false;

    QMouseEvent *mevent = static_cast<QMouseEvent *>(event);
    if (mevent->type() == QEvent::MouseButtonPress) {
        if (mevent->button() == Qt::LeftButton) {
            mousePressed = true;
            mousePoint = mevent->globalPos() - w->pos();
            return true;
        }
    } else if (mevent->type() == QEvent::MouseButtonRelease) {
        mousePressed = false;
        return true;
    } else if (mevent->type() == QEvent::MouseMove) {
        if (mousePressed && mevent->buttons() == Qt::LeftButton) {
            w->move(mevent->globalPos() - mousePoint);
            return true;
        }
    }

    return QObject::eventFilter(obj, event);
}

main.cpp 里添加 appinitdrag.h,然后在要设定拖拽的 widget 窗口的构造函数里添加代码

    this->setProperty("canMove", true); // 设置可以拖拽的属性
    this->setWindowFlags(Qt::FramelessWindowHint); // 设置无边窗
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值