往期回顾:
【QT入门】 自定义标题栏界面qss美化+按钮功能实现-CSDN博客
【QT入门】 无边框窗口设计之实现窗口阴影-CSDN博客
【QT入门】 无边框窗口设计之实现圆角窗口-CSDN博客
【QT入门】 无边框窗口设计综合运用之自定义标题栏带圆角阴影的窗口
一、最终效果
二、知识点分析
其实就是几个知识点的综合运用:
1、自定义标题栏,双击放大效果
2、带窗口阴影,带窗口圆角
3、无边框窗口,实现拉伸效果
由于都是讲解过的知识点,就不再过多讲述,我直接简单说一下每个类的功能,具体的类逻辑实现讲解大家可以参考之前的文章即可。
1、无边框窗口,实现边框拉伸类CFrameLessWidgetBase
直接继承这个类用可以了。
【QT入门】 设计实现无边框窗口拉伸的公用类-CSDN博客
2、自定义标题栏实现拉伸拖动效果设计样式和按钮功能实现类CTitleBar
【QT入门】对无边框窗口自定义标题栏并实现拖动和拉伸效果-CSDN博客
【QT入门】 自定义标题栏界面qss美化+按钮功能实现-CSDN博客
3、底层类和顶层类综合运用实现窗口阴影(窗口圆角放在标题栏类一起设置了)
【QT入门】 无边框窗口设计之实现圆角窗口-CSDN博客
三、完整示例代码
1、 MainWidget.h
#pragma once
#include <QtWidgets/QWidget>
#include "CFrameLessWidgetBase.h"
#include "CTopWidget.h"
#include <QVBoxLayout>
#include <QGraphicsDropShadowEffect>
//派生于CFrameLessWidgetBase
class MainWidget : public CFrameLessWidgetBase
{
Q_OBJECT
public:
MainWidget(QWidget *parent = Q_NULLPTR);
private slots:
void onClose();
void onDoMax(bool isMax);
private:
QVBoxLayout* m_pMainVLay = nullptr;
CTopWidget* m_pTopWidget = nullptr;
QGraphicsDropShadowEffect* m_pShadow = nullptr;
};
2、 MainWidget.cpp
#include "MainWidget.h"
MainWidget::MainWidget(QWidget *parent)
: CFrameLessWidgetBase(parent)
{
//设置窗体透明
this->setAttribute(Qt::WA_TranslucentBackground, true);
m_pMainVLay = new QVBoxLayout(this);
m_pTopWidget = new CTopWidget(this);
m_pMainVLay->addWidget(m_pTopWidget);
int shadow_width = 30;
m_pMainVLay->setContentsMargins(shadow_width, shadow_width, shadow_width, shadow_width);
setLayout(m_pMainVLay);
//给顶层widget设置背景颜色,不然看不见,因为底层widget已经透明了
m_pTopWidget->setStyleSheet("background-color:rgb(255, 254, 253)");
m_pShadow = new QGraphicsDropShadowEffect(this);
//设置阴影距离
m_pShadow->setOffset(0, 0);
//设置阴影颜色 686868
m_pShadow->setColor(QColor("#0000FF"));
//设置阴影区域
m_pShadow->setBlurRadius(shadow_width - 5);
//给顶层QWidget设置阴影
m_pTopWidget->setGraphicsEffect(m_pShadow);
connect(m_pTopWidget, &CTopWidget::sig_close, this, &MainWidget::onClose);
connect(m_pTopWidget, &CTopWidget::sig_max, this, &MainWidget::onDoMax);
}
void MainWidget::onClose()
{
close();
}
void MainWidget::onDoMax(bool isMax)
{
int shadow_width = 25;
if (isMax)
{
shadow_width = 0;
}
else
{
}
m_pMainVLay->setContentsMargins(shadow_width, shadow_width, shadow_width, shadow_width);
//设置阴影区域
m_pShadow->setBlurRadius(shadow_width);
//给顶层QWidget设置阴影
m_pTopWidget->setGraphicsEffect(m_pShadow);
}
3、CTitleBar.h
#pragma once
#include <QWidget>
#include "ui_CTitleBar.h"
class CTitleBar : public QWidget
{
Q_OBJECT
public:
CTitleBar(QWidget *parent = Q_NULLPTR);
~CTitleBar();
protected:
void paintEvent(QPaintEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
signals:
void sig_close();
void sig_max(bool isMax);
private slots:
void on_Clicked();
private:
Ui::CTitleBar ui;
};
4、CTitleBar.cpp
#include "CTitleBar.h"
#include <QMouseEvent>
#include <QStyleOption>
#include <QPushButton>
#include <QPainter>
#include <qt_windows.h>
#pragma comment(lib, "user32.lib")
CTitleBar::CTitleBar(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
//禁止父窗口影响子窗口样式
setAttribute(Qt::WA_StyledBackground);
//左上,右上圆角10;左下,右下圆角0
//QWidget整个窗口都生效
this->setStyleSheet("QWidget{background-color:rgb(54,54,54); \
border-top-left-radius:10px; \
border-top-right-radius:10px; \
border-bottom-left-radius:0px; \
border-bottom-right-radius:0px;}");
ui.label_title->setText(u8"我是标题");
ui.label_title->setStyleSheet("QLabel{font-family: Microsoft YaHei; \
font-size:18px; \
color:#BDC8E2;background-color:rgb(54,54,54);}");
ui.btnSet->setFixedSize(32, 32);
ui.btnSet->setText("");
ui.btnSet->setFlat(true);
ui.btnSet->setStyleSheet("QPushButton{background-image:url(:/titlebar/resource/titlebar/set.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/titlebar/resource/titlebar/set_hover.svg);border:none;}");
ui.btnMin->setFixedSize(32, 32);
ui.btnMin->setText("");
ui.btnMin->setFlat(true);
ui.btnMin->setStyleSheet("QPushButton{background-image:url(:/titlebar/resource/titlebar/min.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/titlebar/resource/titlebar/min_hover.svg);border:none;}");
ui.btnMax->setFixedSize(35, 35);
ui.btnMax->setFlat(true);
ui.btnMax->setText("");
ui.btnMax->setStyleSheet("QPushButton{background-image:url(:/titlebar/resource/titlebar/normal.svg);border:none; \
background-position:center; \
background-repeat:no-repeat;} \
QPushButton:hover{ \
background-color:rgb(99, 99, 99); \
background-image:url(:/titlebar/resource/titlebar/normal_hover.svg);border:none;}");
ui.btnClose->setFixedSize(32, 32);
ui.btnClose->setFlat(true);
ui.btnClose->setText("");
ui.btnClose->setStyleSheet("QPushButton{background-image:url(:/titlebar/resource/titlebar/close.svg);border:none}" \
"QPushButton:hover{" \
"background-color:rgb(99, 99, 99);" \
"background-image:url(:/titlebar/resource/titlebar/close_hover.svg);border:none;}");
connect(ui.btnMin, SIGNAL(clicked(bool)), this, SLOT(on_Clicked()));
connect(ui.btnMax, SIGNAL(clicked(bool)), this, SLOT(on_Clicked()));
connect(ui.btnClose, SIGNAL(clicked(bool)), this, SLOT(on_Clicked()));
}
CTitleBar::~CTitleBar()
{
}
void CTitleBar::paintEvent(QPaintEvent* event)
{
//决定样式表是否起作用
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
QWidget::paintEvent(event);
}
void CTitleBar::on_Clicked()
{
QPushButton* pButton = qobject_cast<QPushButton*>(sender());
QWidget* pWindow = this->window();
if (pWindow->isTopLevel())
{
if (pButton == ui.btnMin)
{
pWindow->showMinimized();
}
else if (pButton == ui.btnMax)
{
if (pWindow->isMaximized())
{
pWindow->showNormal();
ui.btnMax->setStyleSheet("QPushButton{background-image:url(:/titlebar/resource/titlebar/normal.svg);border:none; \
background-position:center; \
background-repeat:no-repeat;} \
QPushButton:hover{ \
background-color:rgb(99, 99, 99); \
background-image:url(:/titlebar/resource/titlebar/normal_hover.svg);border:none;}");
emit sig_max(false);
}
else
{
pWindow->showMaximized();
ui.btnMax->setStyleSheet("QPushButton{background-image:url(:/titlebar/resource/titlebar/max.svg);border:none; \
background-position:center; \
background-repeat:no-repeat;} \
QPushButton:hover{ \
background-color:rgb(99, 99, 99); \
background-image:url(:/titlebar/resource/titlebar/max_hover.svg);border:none;}");
emit sig_max(true);
}
}
else if (pButton == ui.btnClose)
{
emit sig_close();
}
}
}
void CTitleBar::mousePressEvent(QMouseEvent* event)
{
if (ReleaseCapture())
{
QWidget* pWindow = this->window();
if (pWindow->isTopLevel())
{
SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
}
}
event->ignore();
}
void CTitleBar::mouseDoubleClickEvent(QMouseEvent* event)
{
emit ui.btnMax->clicked();
}
5、CTopWidget.h
#pragma once
#include <QWidget>
class CTopWidget : public QWidget
{
Q_OBJECT
public:
CTopWidget(QWidget* p = nullptr);
~CTopWidget();
signals:
void sig_close();
void sig_max(bool isMax);
};
6、CTopWidget.cpp
#include "CTopWidget.h"
#include "CTitleBar.h"
#include <QVBoxLayout>
CTopWidget::CTopWidget(QWidget* p)
:QWidget(p)
{
setAttribute(Qt::WA_StyledBackground);
this->setStyleSheet("QWidget{background-color:rgb(255, 254, 253);border-radius:10px;}");
//this->setStyleSheet("QWidget{background-color:rgb(255, 254, 253); \
// border-bottom-left-radius:15px; \
// border-bottom-right-radius:15px;}");
QVBoxLayout* pVLay = new QVBoxLayout(this);
CTitleBar* pTitle = new CTitleBar(this);
QWidget* pWidget = new QWidget(this);
//需要指定pWidget最小尺寸,或最大尺寸
pWidget->setMinimumSize(1200, 800);
pVLay->addWidget(pTitle);
pVLay->addWidget(pWidget);
pVLay->setContentsMargins(0, 0, 0, 0);
setLayout(pVLay);
connect(pTitle, &CTitleBar::sig_close, this, &CTopWidget::sig_close);
connect(pTitle, &CTitleBar::sig_max, this, &CTopWidget::sig_max);
}
CTopWidget::~CTopWidget()
{
}
都看到这里了,点个赞再走呗朋友~
加油吧,预祝大家变得更强!