效果: 可拖动拉伸
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_OBJECT
public:
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,需要识别HoverMove
this->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();
}