需求是这样的:在主窗体上会根据业务弹出一个临时的小界面,类似于提示的标签。希望这个标签可以鼠标拖拽移动位置,且标签的拖拽范围只能在主界面范围内,不可以拖出去。
我的处理方式是在子标签上进行,下面来聊一下实现的思路:
- 处理拖拽可移动,鼠标的三个事件肯定不能少,mousePressEvent(鼠标按下),mouseMoveEvent(鼠标移动)和mouseReleaseEvent(鼠标释放)
- 在mousePressEvent事件中记录鼠标按下状态(在mouseMoveEvent事件中使用),记录鼠标点击时的起始位置(方便在mouseMoveEvent事件中计算需要移动的位置)
- 在mouseReleaseEvent中将鼠标按下状态恢复,在mouseMoveEvent事件中不再需要处理拖拽
- 在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;
}