qt 无边框窗体拖动、拉伸
程序员文章站
2022-07-14 13:05:43
...
关键代码都是看 大神刘典武的 https://me.csdn.net/feiyangqingyun 我只是自己做个笔记
需要定义的变量:
int padding = 4; //鼠标改变形状的区域宽度
//记录鼠标按下时窗体的左上点x、y值和宽、高
int rectX;
int rectY;
int rectW;
int rectH;
//鼠标按下时的坐标点
QPoint lastPos;
//将窗体分为左、上、右、下、左上、右上、左下、右下八个区域,用来确定朝哪个方向拉伸
//剩下的*区域用来拖动窗体
QRect rectLeft;
QRect rectTop;
QRect rectRight;
QRect rectBottom;
QRect rectLeftTop;
QRect rectRightTop;
QRect rectLeftBottom;
QRect rectRightBottom;
//移动和各个方向拉伸的使能
bool moveEnable = false;
bool pressed = false;
bool pressedLeft = false;
bool pressedRight = false;
bool pressedTop = false;
bool pressedBottom = false;
bool pressedLeftTop = false;
bool pressedRightTop = false;
bool pressedLeftBottom = false;
bool pressedRightBottom = false;
初始化:
this->setWindowFlag(Qt::FramelessWindowHint);
setStyleSheet("background:#43CD80");
installEventFilter(this);
//1.使用setMouseTracking(true)对鼠标进行监控(mouseMoveEvent(QMouseEvent *event)),如果WidgetA有个子窗体WidgetB会占据WidgetA的绝大部分空间,那么当鼠标移动到WidgetB上时,WidgetA就会失去对鼠标的监控。
//2.使用setAttribute( Qt::WA_Hover,true)也可以实现对鼠标的监控,相对于setMouseTracking(true)来说,它可以弥补鼠标事件被子窗体获取的问题:
setAttribute(Qt::WA_Hover,true);
主要代码:
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
if (watched == this) {
if (event->type() == QEvent::Resize) {
//重新计算八个描点的区域,描点区域的作用还有就是计算鼠标坐标是否在某一个区域内
int width = this->width();
int height = this->height();
rectLeft = QRect(0, padding, padding, height - padding * 2);
rectTop = QRect(padding, 0, width - padding * 2, padding);
rectRight = QRect(width - padding, padding, padding, height - padding * 2);
rectBottom = QRect(padding, height - padding, width - padding * 2, padding);
rectLeftTop = QRect(0, 0, padding, padding);
rectRightTop = QRect(width - padding, 0, padding, padding);
rectLeftBottom = QRect(0, height - padding, padding, padding);
rectRightBottom = QRect(width - padding, height - padding, padding, padding);
}else if (event->type() == QEvent::HoverMove) {
//设置对应鼠标形状,这个必须放在这里而不是下面,因为可以在鼠标没有按下的时候识别
QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
QPoint point = hoverEvent->pos();
if (rectLeft.contains(point)) {
this->setCursor(Qt::SizeHorCursor);
} else if (rectRight.contains(point)) {
this->setCursor(Qt::SizeHorCursor);
} else if (rectTop.contains(point)) {
this->setCursor(Qt::SizeVerCursor);
} else if (rectBottom.contains(point)) {
this->setCursor(Qt::SizeVerCursor);
} else if (rectLeftTop.contains(point)) {
this->setCursor(Qt::SizeFDiagCursor);
} else if (rectRightTop.contains(point)) {
this->setCursor(Qt::SizeBDiagCursor);
} else if (rectLeftBottom.contains(point)) {
this->setCursor(Qt::SizeBDiagCursor);
} else if (rectRightBottom.contains(point)) {
this->setCursor(Qt::SizeFDiagCursor);
} else {
this->setCursor(Qt::ArrowCursor);
}
if (moveEnable) {
this->setCursor(Qt::OpenHandCursor);
}
//根据当前鼠标位置,计算XY轴移动了多少
int offsetX = point.x() - lastPos.x();
int offsetY = point.y() - lastPos.y();
//根据按下处的位置判断是否是移动控件还是拉伸控件
if (moveEnable) {
this->move(this->x() + offsetX, this->y() + offsetY);
}
if (pressedLeft) {
int resizeW = this->width() - offsetX;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
}
} else if (pressedRight) {
this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
} else if (pressedTop) {
int resizeH = this->height() - offsetY;
if (this->minimumHeight() <= resizeH) {
this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
}
} else if (pressedBottom) {
this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
} else if (pressedLeftTop) {
int resizeW = this->width() - offsetX;
int resizeH = this->height() - offsetY;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
}
} else if (pressedRightTop) {
int resizeW = rectW + offsetX;
int resizeH = this->height() - offsetY;
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
}
} else if (pressedLeftBottom) {
int resizeW = this->width() - offsetX;
int resizeH = rectH + offsetY;
if (this->minimumWidth() <= resizeW) {
this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
}
if (this->minimumHeight() <= resizeH) {
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
} else if (pressedRightBottom) {
int resizeW = rectW + offsetX;
int resizeH = rectH + offsetY;
this->setGeometry(this->x(), this->y(), resizeW, resizeH);
}
}else if (event->type() == QEvent::MouseButtonPress) {
//记住当前控件坐标和宽高以及鼠标按下的坐标
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
rectX = this->x();
rectY = this->y();
rectW = this->width();
rectH = this->height();
lastPos = mouseEvent->pos();
//判断按下的手柄的区域位置
if (rectLeft.contains(lastPos)) {
pressedLeft = true;
} else if (rectRight.contains(lastPos)) {
pressedRight = true;
} else if (rectTop.contains(lastPos)) {
pressedTop = true;
} else if (rectBottom.contains(lastPos)) {
pressedBottom = true;
} else if (rectLeftTop.contains(lastPos)) {
pressedLeftTop = true;
} else if (rectRightTop.contains(lastPos)) {
pressedRightTop = true;
} else if (rectLeftBottom.contains(lastPos)) {
pressedLeftBottom = true;
} else if (rectRightBottom.contains(lastPos)) {
pressedRightBottom = true;
} else {
moveEnable = true;
}
} else if (event->type() == QEvent::MouseMove) {
// //改成用HoverMove识别
} else if (event->type() == QEvent::MouseButtonRelease) {
//恢复所有
moveEnable = false;
pressedLeft = false;
pressedRight = false;
pressedTop = false;
pressedBottom = false;
pressedLeftTop = false;
pressedRightTop = false;
pressedLeftBottom = false;
pressedRightBottom = false;
this->setCursor(Qt::ArrowCursor);
}
}
return QObject::eventFilter(watched, event);
}
现在就是在向左和向上拉伸时窗体会抖动,
下一步想看看能不能让鼠标形状在拉伸过程中移动到其他区域时不会改变形状。
上一篇: 哔哩哔哩:笔试题(20190910)
下一篇: 数据结构--------------队列