Qt C++ 实现无边框窗口
// widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QDebug>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QPushButton>
#include <QString>
#include <QWidget>#define PADDING 6enum Location {TOP,BOTTOM,LEFT,RIGHT,TOP_LEFT,TOP_RIGHT,BOTTOM_LEFT,BOTTOM_RIGHT,CENTER
};class Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget* parent = nullptr);~Widget();protected:void mousePressEvent(QMouseEvent* event);void mouseMoveEvent(QMouseEvent* event);void mouseReleaseEvent(QMouseEvent* event);private:void setCursorShape(const QPoint& point);private:// 左键有没有按下bool isLeftPressed;// 鼠标按下的位置 偏移QPoint mouseOffset;Location location;
};
#endif // WIDGET_H
// widget.cpp
#include "widget.h"Widget::Widget(QWidget* parent) : QWidget(parent) {// 设置窗口的宽高this->setMinimumWidth(500);this->setMinimumHeight(300);// 设置背景色this->setStyleSheet("background: #303030");// 添加两个按钮 - 水平布局QHBoxLayout* layout = new QHBoxLayout(this);layout->setSpacing(10);layout->setContentsMargins(10, 10, 10, 10);QPushButton* btn1 = new QPushButton("确定");QPushButton* btn2 = new QPushButton("取消");layout->addWidget(btn1);layout->addWidget(btn2);QString style = R"(QPushButton {background-color: rgb(64, 64, 64);font: 16px "Microsoft YaHei";color: rgb(200, 200, 200);border-radius: 5px;padding: 5px;}QPushButton:hover {background-color: rgb(40, 40, 40);}QPushButton:pressed {background-color: rgb(64, 64, 64);})";btn1->setStyleSheet(style);btn2->setStyleSheet(style);// 去除标题栏this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);this->isLeftPressed = false;// 开启鼠标追踪this->setMouseTracking(true);
}Widget::~Widget() {}void Widget::mousePressEvent(QMouseEvent* event) {switch (event->button()) {case Qt::RightButton:this->close();break;case Qt::LeftButton:this->isLeftPressed = true;if (location == CENTER) {this->mouseOffset =event->globalPos() - this->frameGeometry().topLeft();}break;}
}void Widget::mouseMoveEvent(QMouseEvent* event) {QPoint globalPos = event->globalPos();QRect rect = this->rect();QPoint topLeft = mapToGlobal(rect.topLeft());QPoint bottomRight = mapToGlobal(rect.bottomRight());// 1. 鼠标未按下if (!this->isLeftPressed) {this->setCursorShape(globalPos);return;}// 2. 鼠标按下, 在CENTER位置按下if (this->location == CENTER) {move(globalPos - mouseOffset);event->accept();return;}// 3. 缩放QRect rMove(topLeft, bottomRight);switch (location) {case TOP:// 窗口达到最小高度后,会被鼠标 “向下推走”if (bottomRight.y() - globalPos.y() > this->minimumHeight())rMove.setY(globalPos.y());break;case BOTTOM:rMove.setHeight(globalPos.y() - topLeft.y());break;case LEFT:if (bottomRight.x() - globalPos.x() > this->minimumWidth())rMove.setX(globalPos.x());break;case RIGHT:rMove.setWidth(globalPos.x() - topLeft.x());break;case TOP_LEFT:if (bottomRight.y() - globalPos.y() > this->minimumHeight())rMove.setY(globalPos.y());if (bottomRight.x() - globalPos.x() > this->minimumWidth())rMove.setX(globalPos.x());break;case TOP_RIGHT:if (bottomRight.y() - globalPos.y() > this->minimumHeight())rMove.setY(globalPos.y());rMove.setWidth(globalPos.x() - topLeft.x());break;case BOTTOM_LEFT:rMove.setHeight(globalPos.y() - topLeft.y());if (bottomRight.x() - globalPos.x() > this->minimumWidth())rMove.setX(globalPos.x());break;case BOTTOM_RIGHT:rMove.setHeight(globalPos.y() - topLeft.y());rMove.setWidth(globalPos.x() - topLeft.x());break;default:break;}this->setGeometry(rMove);
}void Widget::mouseReleaseEvent(QMouseEvent* event) {if (event->button() == Qt::LeftButton) {isLeftPressed = false;}
}void Widget::setCursorShape(const QPoint& point) {QRect rect = this->rect();QPoint topLeft = mapToGlobal(rect.topLeft());QPoint bottomRight = mapToGlobal(rect.bottomRight());int x = point.x();int y = point.y();if (x >= topLeft.x() && x <= topLeft.x() + PADDING && y >= topLeft.y() &&y <= topLeft.y() + PADDING) {// 左上角location = TOP_LEFT;this->setCursor(QCursor(Qt::SizeFDiagCursor));} else if (x <= bottomRight.x() && x >= bottomRight.x() - PADDING &&y <= bottomRight.y() && y >= bottomRight.y() - PADDING) {// 右下角location = BOTTOM_RIGHT;this->setCursor(QCursor(Qt::SizeFDiagCursor));} else if (x >= topLeft.x() && x <= topLeft.x() + PADDING &&y <= bottomRight.y() && y >= bottomRight.y() - PADDING) {// 左下角location = BOTTOM_LEFT;this->setCursor(QCursor(Qt::SizeBDiagCursor));} else if (x <= bottomRight.x() && x >= bottomRight.x() - PADDING &&y >= topLeft.y() && y <= topLeft.y() + PADDING) {// 右上角location = TOP_RIGHT;this->setCursor(QCursor(Qt::SizeBDiagCursor));} else if (x >= topLeft.x() && x <= topLeft.x() + PADDING) {// 左边location = LEFT;this->setCursor(QCursor(Qt::SizeHorCursor));} else if (x >= bottomRight.x() - PADDING && x <= bottomRight.x()) {// 右边location = RIGHT;this->setCursor(QCursor(Qt::SizeHorCursor));} else if (y >= topLeft.y() && y <= topLeft.y() + PADDING) {// 上边location = TOP;this->setCursor(QCursor(Qt::SizeVerCursor));} else if (y >= bottomRight.y() - PADDING && y <= bottomRight.y()) {// 下边location = BOTTOM;this->setCursor(QCursor(Qt::SizeVerCursor));} else {location = CENTER;this->setCursor(QCursor(Qt::ArrowCursor));}
}