效果: 可拖动拉伸
ui:设计如下
样式表:在ui CustomDialog 里设置的
#widget_title{background: #E6F1EB;border-top-left-radius: 20px;border-top-right-radius: 20px;}#widget_client{background-color: rgb(255, 255, 255);border-bottom-left-radius: 20px; border-bottom-right-radius: 20px;}#label_title{background-color: #E6F1EB;font-family: Source Han Sans CN;font-size: 24px;font-weight: bold;}
头文件
#ifndef CUSTOMDIALOG_H
#define CUSTOMDIALOG_H#include <QDialog>
#include <QWidget>namespace Ui {
class CustomDialog;
}class CustomDialog : public QDialog
{Q_OBJECTpublic:explicit CustomDialog(QWidget *parent = nullptr);~CustomDialog();void setTitleText(const QString text);
private slots:void on_toolButton_quit_clicked();private:virtual void paintEvent(QPaintEvent *event) override; //重绘,virtual bool eventFilter(QObject *watched, QEvent *event);
private:Ui::CustomDialog *ui;int padding; //边距bool moveEnable; //可移动bool resizeEnable; //可拉伸bool pressed; //鼠标按下bool pressedLeft; //鼠标按下左侧bool pressedRight; //鼠标按下右侧bool pressedTop; //鼠标按下上侧bool pressedBottom; //鼠标按下下侧bool pressedLeftTop; //鼠标按下左上侧bool pressedRightTop; //鼠标按下右上侧bool pressedLeftBottom; //鼠标按下左下侧bool pressedRightBottom; //鼠标按下右下侧int rectX, rectY, rectW, rectH; //窗体坐标+宽高QPoint lastPos; //鼠标按下处坐标QRect rectLeft; //左侧区域QRect rectRight; //右侧区域QRect rectTop; //上侧区域QRect rectBottom; //下侧区域QRect rectLeftTop; //左上侧区域QRect rectRightTop; //右上侧区域QRect rectLeftBottom; //左下侧区域QRect rectRightBottom; //右下侧区域
};#endif // CUSTOMDIALOG_H
cpp
#include "customdialog.h"
#include "ui_customdialog.h"
#include <QStyleOption>
#include <QPainter>
#include <QMouseEvent>
CustomDialog::CustomDialog(QWidget *parent) :QDialog(parent),ui(new Ui::CustomDialog)
{ui->setupUi(this);setWindowFlags(Qt::FramelessWindowHint);setAttribute(Qt::WA_TranslucentBackground);//设置窗口透明化ui->toolButton_quit->setStyleSheet("QToolButton{border-radius: 20px;opacity: 1;""font-family: Source Han Sans CN;""font-size: 24px;""font-weight: norm;""background-color:#E6F1EB;}");padding = 8;moveEnable = true;resizeEnable = true;pressed = false;pressedLeft = false;pressedRight = false;pressedTop = false;pressedBottom = false;pressedLeftTop = false;pressedRightTop = false;pressedLeftBottom = false;pressedRightBottom = false;this->setMouseTracking(true);//绑定事件过滤器this->installEventFilter(this);//设置悬停为真,必须设置这个,不然当父窗体里边还有子窗体全部遮挡了识别不到MouseMove,需要识别HoverMovethis->setAttribute(Qt::WA_Hover, true);
}CustomDialog::~CustomDialog()
{delete ui;
}void CustomDialog::setTitleText(const QString text)
{ui->label_title->setText(text);
}void CustomDialog::paintEvent(QPaintEvent *)
{QStyleOption opt;opt.init(this);QPainter painter(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);}bool CustomDialog::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 = (QHoverEvent *)event;QPoint point = hoverEvent->pos();if (resizeEnable) {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);}}//根据当前鼠标位置,计算XY轴移动了多少int offsetX = point.x() - lastPos.x();int offsetY = point.y() - lastPos.y();//根据按下处的位置判断是否是移动控件还是拉伸控件if (moveEnable) {if (pressed) {this->move(this->x() + offsetX, this->y() + offsetY);}}if (resizeEnable) {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 = (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 {pressed = true;}} else if (event->type() == QEvent::MouseMove) {//改成用HoverMove识别} else if (event->type() == QEvent::MouseButtonRelease) {//恢复所有pressed = 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);
}void CustomDialog::on_toolButton_quit_clicked()
{reject();
}