功能: 鼠标按住窗口的自定义标题栏后,移动拖动整个窗口功能
实现方式:
方法一:其中CVideoPlayerApp是自定义标题栏的QWidget。
void CVideoPlayerApp::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
if (event->y() < VALUE_DIS || event->x() < VALUE_DIS || rect().width() - event->x() < VALUE_DIS)
{
event->ignore();
return;
}
m_ptPress = event->globalPos();
m_bLeftButtonPress = true;
}
event->ignore();
}
void CVideoPlayerApp::mouseMoveEvent(QMouseEvent *event)
{
if (m_bLeftButtonPress)
{
m_ptMove = event->globalPos();
int x = (m_ptMove - m_ptPress).x();
int y = (m_ptMove - m_ptPress).y();
emit sigMouseMoveEvent(x, y); //触发对应的槽函数,移动窗口
m_ptPress = m_ptMove;
}
event->ignore();
}
void CVideoPlayerApp::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_bLeftButtonPress = false;
}
event->ignore();
}
void CVideoPlayerApp::slotMouseMoveEvent( int x, int y )
{
move(this->pos().x() + x, this->pos().y() + y);
// 更新窗口位置
updateWindowsPos();
}
方法二:其中MarkBuildDrawWgt就是一个含有自定义标题栏的QWidget。
void MarkBuildDrawWgt::mousePressEvent(QMouseEvent *event)
{
if (event->button()==Qt::LeftButton && ui.frameMarkBuildDarwTitle->underMouse())
{
m_bPress = true ;
m_lastPoint = event->pos(); //相对坐标
}
QWidget::mousePressEvent(event);
}
void MarkBuildDrawWgt::mouseMoveEvent(QMouseEvent *event)
{
if (m_bPress)
{
this->move(pos()+(event->pos()-m_lastPoint));
}
QWidget::mouseMoveEvent(event);
}
void MarkBuildDrawWgt::mouseReleaseEvent(QMouseEvent *event)
{
m_bPress = false ;
QWidget::mouseReleaseEvent(event);
}
方法二思路: 鼠标按下事件中监听是否为鼠标左键,并且是否在自定义标题内 --> 记录下按下的相对坐标位置,并记录按下的状态(bool)。
鼠标移动事件中监听是否正处于按下状态 --》 计算当前鼠标相对位置 - 按下的相对坐标位置 --》 移动窗口相应的距离 --》更新按下的相对坐标位置。
【问题】方法二中为什么相对坐标可以,感觉都是窗口move结束和开始的差值。为什么方法一中,需要不断更新上一个点的坐标?而方法二却不用?
假设,鼠标按下的点是子窗口的左上角的点,也就是(0,0)。那么但鼠标向左在移动10px后,其鼠标相对子窗口而言是(-10,0)。然后子窗口向左移动10px后,这个过程中,鼠标移动只有这一次执行move() ,而不是1px1px的执行。
然后当再次执行时候,鼠标向下移动10px的时候,其还是(0,10)而不是(-10,10)。这里就是关键,第二次执行event->pos()的时候,其减去的那个按下的点相对坐标没边,但其绝对坐标其实已经改变了,这就是为什么相对坐标可以直接相减,而不用在对按下点重新赋值。而用绝对路径的方法时,如果还用按下的点的绝对坐标为准,那么第二次计算的时候,如果把第一次窗口移动会原来的位置就每错了。
另一个关键点: 无法方法一还是二的,其MouseMoveEvent()其不要看成连续的,看出是间段的理解就好了。
其实可以用向量的方法来理解。
【问题】这个与Mouse Tracking
有关系吗?我没有设置这个也可以正常运行。
如果想触发
mouseMoveEvent()
这个鼠标移动的响应函数,则必须要设置窗体(或控件)
是可以Mouse Tracking
的,不然程序不会进入mouseMoveEvent()
函数。
【注意】从实现效果上来看,用复杂的子窗口,他在移动的时候,会出现拖尾重影的效果,无论是用相对还是全局坐标。
相对坐标: 相对于当前MousePressEvent的窗口而已,即子窗口。
绝对坐标: 相对于桌面而已的坐标。