通过执行鼠标按下事件响应函数 mousePressEvent(QMouseEvent*) 和鼠标移动事件响应函数 mouseMoveEvent(QMouseEvent*)的重定义,实现自定义的鼠标拖拽移动窗口
void Demo::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
dragPosition = event->globalPos() - frameGeometry().topLeft();
event->accept();
}
if (event->button() == Qt::RightButton)
{
//close();
}
}
void Demo::mouseMoveEvent(QMouseEvent *event)
{
//if (event->buttons()&Qt::LeftButton) //只要鼠标左键被按压就执行(左右同按也执行)
if (event->buttons() == Qt::LeftButton) //只有鼠标左键被按压才执行
{
move(event->globalPos() - dragPosition);
event->accept();
}
}
先通过鼠标响应事件函数 mousePressEvent(QMouseEvent*),获取鼠标按压点相对窗口左上角的坐标差,
然后在鼠标移动事件函数 mouseMoveEvent(QMouseEvent*) 中根据移动后的鼠标位置和上一步得到的坐标差得到当前窗口左上角坐标,然后调用 move 函数将窗口移动至此
void MoveWindow::mousePressEvent(QMouseEvent *event)
{
//判断位置
if (event->button() == Qt::LeftButton)
{
bool shouldMove = isPointInDragnWidget(getDragnWidget(), event->pos());
if (shouldMove) {
pressedPoint = event->pos(); //触发鼠标按压事件的点
isMove = true;
}
event->ignore();
}
}
void MoveWindow::mouseMoveEvent(QMouseEvent *event)
{
if ((event->buttons() == Qt::LeftButton) && isMove == true) {
QPoint currPoint = this->pos();
this->move(currPoint - (pressedPoint - event->pos() ));
}
}
void MoveWindow::mouseReleaseEvent(QMouseEvent *event)
{
isMove = false;
}
bool MoveWindow::isPointInDragnWidget(const QWidget *widget, const QPoint &point)
{
//判断位置
QRect rect = widget->rect();
bool isIn = point.x() >= rect.left() && point.x() <= rect.right() && point.y() >= rect.top() && point.y() <= rect.bottom();
return isIn;
}
当我们希望只对窗口的某一部分提供鼠标拖拽移动窗口功能时,采用这种模式。
这里关于坐标差值以及窗口当前位置的计算方式和上面略有不同,不过原理都是一样的。
主要是增加了对位置的判断。
在 mousePressEvent(QMouseEvent*) 函数中先调用接口判断鼠标按压点是否在允许拖拽的组件区域内,然后再计算坐标差值找到当前窗口坐标进行移动
第二种方式的完整代码由一个类实现,实际使用时继承到自己的窗口类中,下面是代码
.h文件
#ifndef MOVEWINDOW_H
#define MOVEWINDOW_H
#include
class MoveWindow : public QWidget
{
Q_OBJECT
public:
explicit MoveWindow(QWidget *parent = Q_NULLPTR);
protected:
/**
* @brief 鼠标按下,准备拖动窗体
* @param event
*/
void mousePressEvent(QMouseEvent *event);
/**
* @brief 鼠标移动,处理窗体拖动
* @param event
*/
void mouseMoveEvent(QMouseEvent *event);
/**
* @brief 释放鼠标
* @param event
*/
void mouseReleaseEvent(QMouseEvent *event);
/**
* @brief 获取可拖动控件,必须由子类指定
* @return
*/
virtual QWidget*getDragnWidget() = 0;
/**
* @brief 判断鼠标点击的位置是否进入可拖动区域
* @param widget 可拖动控件位置
* @param point 鼠标点击位置
* @return
*/
bool isPointInDragnWidget(const QWidget*widget, const QPoint &point);
/**
* @brief 标志是否移动窗体
*/
bool isMove;
/**
* @brief 鼠标按下去的点
*/
QPoint pressedPoint;
};
#endif // !MOVEWINDOW_H
.cpp文件
#include "MoveWindow.h"
#include
#include
#include
#include
#include
MoveWindow::MoveWindow(QWidget *parent)
: QWidget(parent)
{
//设置窗体为无边框
this->setWindowFlags(Qt::FramelessWindowHint);
//设置底层背景透明
this->setAttribute(Qt::WA_TranslucentBackground);
//setAttribute(Qt::WA_TranslucentBackground);
}
void MoveWindow::mousePressEvent(QMouseEvent *event)
{
//判断位置
if (event->button() == Qt::LeftButton)
{
bool shouldMove = isPointInDragnWidget(getDragnWidget(), event->pos());
if (shouldMove) {
pressedPoint = event->pos(); //触发鼠标按压事件的点
isMove = true;
}
event->ignore();
//event->accept();
}
}
void MoveWindow::mouseMoveEvent(QMouseEvent *event)
{
if ((event->buttons() == Qt::LeftButton) && isMove == true) {
this->move(this->pos() - (pressedPoint - event->pos() ));
}
}
void MoveWindow::mouseReleaseEvent(QMouseEvent *event)
{
isMove = false;
}
bool MoveWindow::isPointInDragnWidget(const QWidget *widget, const QPoint &point)
{
//判断位置
QRect rect = widget->rect();
bool isIn = point.x() >= rect.left() && point.x() <= rect.right() && point.y() >= rect.top() && point.y() <= rect.bottom();
return isIn;
}
.h文件中的虚函数 getDragnWidget() 在子类中要实现,用来获取允许鼠标拖拽移动的组件
//.h
protected:
QWidget* getDragnWidget();
//.cpp
QWidget * MainInterface::getDragnWidget()
{
return ui.wgt_top;
}