Qt实现控制在父窗体内可以拖动,且拖动范围不能超出父窗体

需求是这样的:在主窗体上会根据业务弹出一个临时的小界面,类似于提示的标签。希望这个标签可以鼠标拖拽移动位置,且标签的拖拽范围只能在主界面范围内,不可以拖出去。

我的处理方式是在子标签上进行,下面来聊一下实现的思路:

  1. 处理拖拽可移动,鼠标的三个事件肯定不能少,mousePressEvent(鼠标按下),mouseMoveEvent(鼠标移动)和mouseReleaseEvent(鼠标释放)
  2. 在mousePressEvent事件中记录鼠标按下状态(在mouseMoveEvent事件中使用),记录鼠标点击时的起始位置(方便在mouseMoveEvent事件中计算需要移动的位置)
  3. 在mouseReleaseEvent中将鼠标按下状态恢复,在mouseMoveEvent事件中不再需要处理拖拽
  4. 在mouseMoveEvent事件中根据移动时鼠标的起始位置和当前位置,计算需要移动的位置。此时需要注意,因为是作为子空间,所以子控件的移动范围需要进行矫正,否则会出现子控件拖到了主界面之外看不见的地方了,如果此时释放鼠标就再也找不到我们的子控件了

废话不多说直接上代码:

#ifndef SONCTRL_H
#define SONCTRL_H

#include <QWidget>
#include <QMouseEvent>
#include <QPoint>

namespace Ui {
class SonCtrl;
}

class SonCtrl : public QWidget
{
    Q_OBJECT

public:
    explicit SonCtrl(QWidget *parent = nullptr);
    ~SonCtrl();

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *);
    
private:
    Ui::SonCtrl *ui;

    bool m_isPressed = false;//是否鼠标按下的标识
    QPoint m_startPos;//开始拖拽时鼠标点击控件的相对位置
    QPoint m_startMovePos;

    int m_nOffLeft = 0;
    int m_nOffRight = 0;
    int m_nOffTop = 0;
    int m_nOffBottom = 0;

    QWidget *m_parent = nullptr;//保存父控件的指针
};

#endif // SONCTRL_H
#include "SonCtrl.h"
#include "ui_SonCtrl.h"

SonCtrl::SonCtrl(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SonCtrl)
{
    m_parent = parent;
    ui->setupUi(this);
    this->setObjectName("SonCtrl");
}

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

void SonCtrl::mousePressEvent(QMouseEvent *event)
{
    m_isPressed = true;
    m_startMovePos = event->globalPos() - this->frameGeometry().topLeft();

    m_startPos = this->mapFromGlobal(QCursor::pos());//开始拖拽时点击控件的什么位置
    if (nullptr != m_parent)
    {
        m_nOffLeft = m_startPos.rx();
        m_nOffRight = m_parent->width()- (this->width());
        m_nOffTop = m_startPos.ry();
        m_nOffBottom = m_parent->height()- (this->height());
    }
}

void SonCtrl::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isPressed && nullptr != m_parent)
    {
        QPoint pos = this->mapToGlobal(event->pos() - m_startMovePos);
        int rx = pos.rx();
        int ry = pos.ry();
        QPoint tmpPos;
        if(rx < 0)//left矫正,防止子控件被拖出左侧
        {
            rx = 0;
        }
        if(ry<0)//top矫正,防止子控件被拖出上测
        {
            ry = 0;
        }
        if(rx > m_nOffRight)//right矫正,防止子控件被拖出右侧
        {
            rx=m_nOffRight;
        }
        if(ry > m_nOffBottom)//bottom矫正,防止子控件被拖出下侧
        {
            ry = m_nOffBottom;
        }

        tmpPos= QPoint(rx,ry);
        move(tmpPos);//移动子控件
    }
}

void SonCtrl::mouseReleaseEvent(QMouseEvent *)
{
    m_isPressed = false;
}
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值