ch3_1 查看QWidget类源码了解其使用方法
Qt所有的窗口、控件以及布局都是派生于Qwidget,Qt很多问题都可以从Qwidget类找到答案,学习Qt大部分就是在与QWidget打交道。
ch3_2 无边框窗口的基本实现
直接看代码:
MainWidget.h
#pragma once
#include <QtWidgets/QWidget>
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr);
~MainWidget();
private:
void mouseMoveEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
private:
QPoint diff_pos;
QPoint window_pos;
QPoint mouse_pos;
};
MainWidget.cpp
#include "MainWidget.h"
#include <QMouseEvent>
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
}
MainWidget::~MainWidget()
{}
void MainWidget::mousePressEvent(QMouseEvent * event)
{
mouse_pos = event->globalPosition().toPoint(); //这句QT5和QT6方法有所不同,在5版本中,使用globalPos,6版本是globalPosition返回值是一个QPointF类型
window_pos = this->pos();
diff_pos = mouse_pos - window_pos;
}
void MainWidget::mouseMoveEvent(QMouseEvent* event)
{
QPoint pos = event->globalPosition().toPoint();
//this->move(pos);
this->move(pos - diff_pos);
}
编译结果:

ch3_3 给无边框窗口添加自定义标题栏并实现拖拽拉伸
本小节的文件结构如下:

MainWidget类:主窗口
CTitleBar类:标题栏类
CFrameLessWidgetBase类:无边框窗口类,当需要使用创建无边框窗口时,可以使用该类派生子类,拥有基本的无边框窗口的方法属性
任务1:代码实现无边框窗口布局
单独写写一个标题栏类,标题栏布局如下:

CTitleBar.h
#pragma once
#include <QWidget>
#include <QPushbutton>
#include <QLabel>
#include <QMouseEvent>
class CTitlebar : public QWidget
{
Q_OBJECT
public:
CTitlebar(QWidget* p = nullptr);
~CTitlebar();
private:
void initUI();
void mousePressEvent(QMouseEvent* event) override;
private:
QLabel* m_pLogo;
QLabel* m_pTitleTextLabel;
QPushButton* m_pSetBtn;
QPushButton* m_pMinBtn;
QPushButton* m_pMaxBtn;
QPushButton* m_pCloseBtn;
};
CTitlebar.cpp
#include "CTitlebar.h"
#include <QHBoxLayout>
#pragma warning(disable:4996) //为了避免出现C4996报错添加此句
#include <qt_windows.h>
CTitlebar::CTitlebar(QWidget* p) : QWidget(p)
{
initUI();
}
CTitlebar::~CTitlebar()
{
}
void CTitlebar::initUI()
{
//禁止父窗口影响子窗口样式
setAttribute(Qt::WA_StyledBackground);
this->setFixedHeight(40);
this->setStyleSheet("background-color:rgb(100,100,100)");
m_pLogo = new QLabel(this);
m_pLogo->setFixedSize(32, 32);
m_pLogo->setStyleSheet("background-color:rgb(200,10,10)");
m_pTitleTextLabel = new QLabel(this);
m_pTitleTextLabel->setText("我是标题");
m_pTitleTextLabel->setFixedWidth(120);
m_pSetBtn = new QPushButton(this);
m_pSetBtn->setFixedSize(32, 32);
m_pMinBtn = new QPushButton(this);
m_pMinBtn->setFixedSize(32, 32);
m_pMaxBtn = new QPushButton(this);
m_pMaxBtn->setFixedSize(32, 32);
m_pCloseBtn = new QPushButton(this);
m_pCloseBtn->setFixedSize(32, 32);
QHBoxLayout* pHlay = new QHBoxLayout(this);
pHlay->addWidget(m_pLogo);
pHlay->addWidget(m_pTitleTextLabel);
pHlay->addStretch();
pHlay->addWidget(m_pSetBtn);
pHlay->addWidget(m_pMinBtn);
pHlay->addWidget(m_pMaxBtn);
pHlay->addWidget(m_pCloseBtn);
pHlay->setContentsMargins(5, 5, 5, 5);
}
//拖拽无边框窗口更好的解决办法
void CTitlebar::mousePressEvent(QMouseEvent* event)
{
if (ReleaseCapture())
{
QWidget* pWindow = this->window();
if (pWindow->isTopLevel())
{
SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
}
}
}
CFrameLessWidgetBase.h
#pragma once
#include <QWidget>
class CFrameLessWidgetBase :
public QWidget
{
public:
CFrameLessWidgetBase(QWidget* p = nullptr);
~CFrameLessWidgetBase() {};
protected:
bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
private:
int m_nBorderWidth = 6; //m_nBorder表示鼠标位于边框缩放范围的宽度
};
CFrameLessWidgetBase.cpp
#include "CFrameLessWidgetBase.h"
#include <qt_windows.h>
#include <windows.h>
#include <windowsx.h>
#pragma comment(lib, "user32.lib")
CFrameLessWidgetBase::CFrameLessWidgetBase(QWidget* p)
:QWidget(p)
{
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
setAttribute(Qt::WA_Hover);
}
//这个函数的作用是实现窗口的拉伸缩放的功能
bool CFrameLessWidgetBase::nativeEvent(const QByteArray& eventType, void* message, qintptr* result)
{
MSG* param = static_cast<MSG*>(message);
switch (param->message)
{
case WM_NCHITTEST:
{
int nX = GET_X_LPARAM(param->lParam) - this->geometry().x();
int nY = GET_Y_LPARAM(param->lParam) - this->geometry().y();
/*if (childAt(nX, nY) != nullptr)
return QWidget::nativeEvent(eventType, message, result);*/
if (nX > m_nBorderWidth && nX < this->width() - m_nBorderWidth &&
nY > m_nBorderWidth && nY < this->height() - m_nBorderWidth)
{
if (childAt(nX, nY) != nullptr)
return QWidget::nativeEvent(eventType, message, result);
}
if ((nX > 0) && (nX < m_nBorderWidth))
*result = HTLEFT;
if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()))
*result = HTRIGHT;
if ((nY > 0) && (nY < m_nBorderWidth))
*result = HTTOP;
if ((nY > this->height() - m_nBorderWidth) && (nY < this->height()))
*result = HTBOTTOM;
if ((nX > 0) && (nX < m_nBorderWidth) && (nY > 0)
&& (nY < m_nBorderWidth))
*result = HTTOPLEFT;
if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
&& (nY > 0) && (nY < m_nBorderWidth))
*result = HTTOPRIGHT;
if ((nX > 0) && (nX < m_nBorderWidth)
&& (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
*result = HTBOTTOMLEFT;
if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
&& (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
*result = HTBOTTOMRIGHT;
return true;
}
}
return false;
}
MainWidgetPro.h
#pragma once
#include <QtWidgets/QWidget>
#include "CTitlebar.h"
#include "CFrameLessWidgetBase.h"
//把无边框窗口抽象成 CFrameLessWidgetBase类,让主窗口从无边框窗口类派生出来
class MainWidgetPro : public CFrameLessWidgetBase
{
Q_OBJECT
public:
MainWidgetPro(QWidget *parent = Q_NULLPTR);
~MainWidgetPro();
private:
void initUI();
private:
CTitlebar* m_pTitleBar = nullptr;
};
MainWidgetPro.cpp
#include "MainWidgetPro.h"
#include "CTitlebar.h"
#include <QVBoxLayout>
MainWidgetPro::MainWidgetPro(QWidget *parent)
: CFrameLessWidgetBase(parent)
{
// 背景透明,防止黑影
//setAttribute(Qt::WA_TranslucentBackground);
initUI();
}
MainWidgetPro::~MainWidgetPro()
{}
void MainWidgetPro::initUI()
{
m_pTitleBar = new CTitlebar(this);
QWidget* w = new QWidget(this);
w->setMinimumSize(800, 600);
QVBoxLayout* pVlay = new QVBoxLayout(this);
pVlay->addWidget(m_pTitleBar);
pVlay->addWidget(w);
pVlay->setContentsMargins(0, 0, 0, 0); //把标题栏不要留有间隙
setLayout(pVlay);
}
//下面实现无边框窗口缩放拉伸借鉴的其他人
/*
* 拖动,缩放实现
*/
//bool MainWidgetPro::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) {
// Q_UNUSED(eventType);
//#ifdef Q_OS_WIN
// MSG* param = static_cast<MSG*>(message);
// switch (param->message) {
// case WM_NCCALCSIZE: {
// // 使用window默认布局,不加这一段代码,系统无法正确进行最大化
// *result = 0;
// return true;
// }
// case WM_NCHITTEST: {
// int nX = cursor().pos().x() - x();
// int nY = cursor().pos().y() - y();
// // 如果鼠标位于子控件上,则不进行处理
// if (childAt(nX, nY) != nullptr) {
// return QWidget::nativeEvent(eventType, message, result);
// }
// // 默认情况下,将鼠标视为在标题栏上
// *result = HTCAPTION;
// // 鼠标区域位于窗体边框,进行缩放
// // 左边框
// if ((nX > 0) && (nX < m_nBorderWidth))
// *result = HTLEFT;
// // 右边框
// if (nX > (this->width() - m_nBorderWidth))
// *result = HTRIGHT;
// // 左上边框
// if ((nY > 0) && (nY < m_nBorderWidth))
// *result = HTTOP;
// // 下边框
// if ((nY > this->height() - m_nBorderWidth) && (nY < this->height()))
// *result = HTBOTTOM;
// // 左上角
// if ((nX > 0) && (nX < m_nBorderWidth) && (nY > 0)
// && (nY < m_nBorderWidth))
// *result = HTTOPLEFT;
// // 右上角
// if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
// && (nY > 0) && (nY < m_nBorderWidth))
// *result = HTTOPRIGHT;
// // 左下角
// if ((nX > 0) && (nX < m_nBorderWidth)
// && (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
// *result = HTBOTTOMLEFT;
// // 右下角
// if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())
// && (nY > this->height() - m_nBorderWidth) && (nY < this->height()))
// *result = HTBOTTOMRIGHT;
// return true;
// }
// }
//#endif
//
// return QWidget::nativeEvent(eventType, message, result);
//}
编译结果:

问题:
1、按照上面贴出来的代码,只能实现拖动窗口,但是不能实现缩放拉伸,如何解决待后续研究;
2、在重写nativeEvent函数时,发现qt6和qt5在函数参数上有所区别,qt6是qintptr* result,qt5是long* result;
3、qt6在pWindow->isTopLevel()这句会报c4996错误,要在头文件处加上#pragma warning(disable:4996)。
任务2:补充标题栏图标并实现按钮功能
代码是在前一个任务上的补充
#pragma once
#include <QWidget>
#include <QPushbutton>
#include <QLabel>
#include <QLineEdit>
#include <QMouseEvent>
class CTitlebar : public QWidget
{
Q_OBJECT
public:
CTitlebar(QWidget* p = nullptr);
~CTitlebar();
private:
void initUI();
void mousePressEvent(QMouseEvent* event) override;
private slots:
void onClicked();
signals:
void sig_close();
private:
QLabel* m_pLogo;
QLabel* m_pTitleTextLabel;
QPushButton* m_pSetBtn;
QPushButton* m_pMinBtn;
QPushButton* m_pMaxBtn;
QPushButton* m_pCloseBtn;
};
----------------------------------------------------------
#include "CTitlebar.h"
#include <QHBoxLayout>
#pragma warning(disable:4996) //为了避免出现C4996报错添加此句
#include <qt_windows.h>
CTitlebar::CTitlebar(QWidget* p) : QWidget(p)
{
initUI();
}
CTitlebar::~CTitlebar()
{
}
void CTitlebar::initUI()
{
/*QLabel* m_pLogo;
QLabel* m_pTitleTextLabel;
QPushButton* m_pSetBtn;
QPushButton* m_pMinBtn;
QPushButton* m_pMaxBtn;
QPushButton* m_pCloseBtn;*/
/*禁止父窗口影响子窗口样式,通过启用 Qt::WA_StyledBackground 属性,
控件的背景可以使用 Qt 样式表(Style Sheet) 进行渲染。如果没有启用此属性,
即使你通过样式表设置背景样式(如 background-color),也可能不会生效。*/
setAttribute(Qt::WA_StyledBackground);
this->setFixedHeight(40);
this->setStyleSheet("background-color:rgb(100,100,100)");
m_pLogo = new QLabel(this);
m_pLogo->setFixedSize(32, 32);
m_pLogo->setStyleSheet("background-image:url(:/MainWidgetPro/resources/titlebar/title_icon.png);border:none");
m_pTitleTextLabel = new QLabel(this);
m_pTitleTextLabel->setText("我是标题");
m_pTitleTextLabel->setFixedWidth(120);
m_pTitleTextLabel->setStyleSheet("QLabel{font-family: Microsoft YaHei; font-size:18px; color:#BDC8E2; background-color:rgb(54,54,54);}");
m_pSetBtn = new QPushButton(this);
m_pSetBtn->setFixedSize(32, 32);
m_pSetBtn->setStyleSheet("QPushButton{background-image:url(:/MainWidgetPro/resources/titlebar/set.svg);border:none}" \
"QPushButton:hover{background-color:rgb(99,99,99);" \
"background-image:url(:/MainWidgetPro/resources/titlebar/set_hover.svg);border:none}");
m_pMinBtn = new QPushButton(this);
m_pMinBtn->setFixedSize(32, 32);
m_pMinBtn->setStyleSheet("QPushButton{background-image:url(:/MainWidgetPro/resources/titlebar/min.svg);border:none}" \
"QPushButton:hover{background-color:rgb(99,99,99);" \
"background-image:url(:/MainWidgetPro/resources/titlebar/min_hover.svg);border:none}");
m_pMaxBtn = new QPushButton(this);
m_pMaxBtn->setFixedSize(32, 32);
m_pMaxBtn->setStyleSheet("QPushButton{background-image:url(:/MainWidgetPro/resources/titlebar/normal.svg);border:none}" \
"QPushButton:hover{background-color:rgb(99,99,99);" \
"background-image:url(:/MainWidgetPro/resources/titlebar/normal_hover.svg);border:none}");
m_pCloseBtn = new QPushButton(this);
m_pCloseBtn->setFixedSize(32, 32);
m_pCloseBtn->setStyleSheet("QPushButton{background-image:url(:/MainWidgetPro/resources/titlebar/close.svg);border:none}" \
"QPushButton:hover{background-color:rgb(99,99,99);" \
"background-image:url(:/MainWidgetPro/resources/titlebar/close_hover.svg);border:none}");
QHBoxLayout* pHlay = new QHBoxLayout(this);
pHlay->addWidget(m_pLogo);
pHlay->addWidget(m_pTitleTextLabel);
pHlay->addStretch();
pHlay->addWidget(m_pSetBtn);
QSpacerItem* pItem1 = new QSpacerItem(20, 20, QSizePolicy::Fixed);
pHlay->addSpacerItem(pItem1);
pHlay->addWidget(m_pMinBtn);
QSpacerItem* pItem2 = new QSpacerItem(20, 20, QSizePolicy::Fixed);
pHlay->addSpacerItem(pItem2);
pHlay->addWidget(m_pMaxBtn);
QSpacerItem* pItem3 = new QSpacerItem(20, 20, QSizePolicy::Fixed);
pHlay->addSpacerItem(pItem3); // 弹簧每次使用时得new出来,不能重复使用
pHlay->addWidget(m_pCloseBtn);
pHlay->setContentsMargins(5, 5, 5, 5); //设置布局的内容边距(即子控件与布局容器边框之间的距离)
//pHlay->setContentsMargins(0,0,0,0);
connect(m_pCloseBtn, &QPushButton::clicked, this, &CTitlebar::onClicked);
connect(m_pMinBtn, &QPushButton::clicked, this, &CTitlebar::onClicked);
connect(m_pMaxBtn, &QPushButton::clicked, this, &CTitlebar::onClicked);
}
//拖拽无边框窗口更好的解决办法
void CTitlebar::mousePressEvent(QMouseEvent* event)
{
if (ReleaseCapture())
{
QWidget* pWindow = this->window();
if (pWindow->isTopLevel())
{
SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
}
}
}
void CTitlebar::onClicked()
{
QPushButton* pButton = qobject_cast<QPushButton*>(sender()); /*获取当前槽函数的触发者(通常是信号的发送者)的指针。
尝试将该指针转换为 QPushButton* 类型。
如果转换成功,将结果赋值给变量 pButton,否则 pButton 为 nullptr。*/
QWidget* pWidget = this->window(); //获取当前窗口部件(QWidget)的指针,即当前控件所属的顶层窗口。
if (pButton == m_pMinBtn)
{
pWidget->showMinimized();
}
else if (pButton == m_pMaxBtn)
{
if (pWidget->isMaximized())
{
pWidget->showNormal();
m_pMaxBtn->setStyleSheet("QPushButton{background-image:url(:/MainWidgetPro/resources/titlebar/normal.svg);border:none}" \
"QPushButton:hover{background-color:rgb(99,99,99);" \
"background-image:url(:/MainWidgetPro/resources/titlebar/normal_hover.svg);border:none}");
}
else
{
pWidget->showMaximized();
m_pMaxBtn->setStyleSheet("QPushButton{background-image:url(:/MainWidgetPro/resources/titlebar/max.svg);border:none}" \
"QPushButton:hover{background-color:rgb(99,99,99);" \
"background-image:url(:/MainWidgetPro/resources/titlebar/max_hover.svg);border:none}");
}
}
else if (pButton == m_pCloseBtn)
{
emit sig_close();
}
}
--------------------------------------------------------------
#pragma once
#include <QWidget>
class CFrameLessWidgetBase :
public QWidget
{
public:
CFrameLessWidgetBase(QWidget* p = nullptr);
~CFrameLessWidgetBase() {};
protected:
//bool nativeEvent(const QByteArray& eventType, void* message, qintptr* result) override;
private:
int m_nBorderWidth = 5; //m_nBorder表示鼠标位于边框缩放范围的宽度
};
--------------------------------------------------------------------
#include "CFrameLessWidgetBase.h"
#include <qt_windows.h>
#include <windows.h>
#include <windowsx.h>
#pragma comment(lib, "user32.lib")
CFrameLessWidgetBase::CFrameLessWidgetBase(QWidget* p)
:QWidget(p)
{
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
setAttribute(Qt::WA_Hover);
}
---------------------------------------------------------------------------
#pragma once
#include <QtWidgets/QWidget>
#include "CTitlebar.h"
#include "CFrameLessWidgetBase.h"
class MainWidgetPro : public CFrameLessWidgetBase
{
Q_OBJECT
public:
MainWidgetPro(QWidget *parent = Q_NULLPTR);
~MainWidgetPro();
private:
void initUI();
private slots:
void on_closeSlot();
private:
CTitlebar* m_pTitleBar = nullptr;
};
--------------------------------------------------------------------------------------------------------
#include "MainWidgetPro.h"
#include "CTitlebar.h"
#include <QVBoxLayout>
MainWidgetPro::MainWidgetPro(QWidget *parent)
: CFrameLessWidgetBase(parent)
{
// 背景透明,防止黑影
//setAttribute(Qt::WA_TranslucentBackground);
initUI();
}
MainWidgetPro::~MainWidgetPro()
{}
void MainWidgetPro::initUI()
{
m_pTitleBar = new CTitlebar(this);
QWidget* w = new QWidget(this);
w->setMinimumSize(800, 600);
QVBoxLayout* pVlay = new QVBoxLayout(this);
pVlay->addWidget(m_pTitleBar);
pVlay->addWidget(w);
pVlay->setContentsMargins(0, 0, 0, 0); //设置布局的内容边距(即子控件与布局容器边框之间的距离);这里设置为 0,表示布局的子控件与布局边框之间没有任何间距
setLayout(pVlay);
connect(m_pTitleBar, &CTitlebar::sig_close, this, &MainWidgetPro::on_closeSlot);
}
void MainWidgetPro::on_closeSlot()
{
close();
}
编译结果:

ch3_7 Qt实现窗口阴影
任务1:给登录窗口添加阴影
预期效果:

窗口阴影的设置需要两层窗口
//设置窗体透明
this->setAttribute(Qt::WA TranslucentBackground, true);
//设置无边框
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
//给顶层widget设置背景颜色,不然看不见,因为底层widget已经透明了
pRealWidget->setStyleSheet(“background-color:rgb(255,254,253)”);
Qt窗囗阴影类 QGraphicsDropshadowEffect
QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect(this);
//设置阴影距离
shadow->setoffset(0,0);
//设置阴影颜色
shadow->setColor(QColor(“#00FF00”));
//设置阴影区域
shadow->setBlurRadius(30);
//给顶层awidget设置阴影
pRealWidget->setGraphicsEffect(shadow);
#pragma once
#include <QtWidgets/QDialog>
class CLoginDlg : public QDialog
{
Q_OBJECT
public:
CLoginDlg(QWidget *parent = nullptr);
~CLoginDlg();
private:
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
private:
QPointF windowPos;
QPointF mousePos;
QPointF dPos;
};
-------------------------------------------
#include "CLoginDlg.h"
#include <CLoginRealWidget.h>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QGraphicsDropShadowEffect>
CLoginDlg::CLoginDlg(QWidget *parent)
: QDialog(parent)
{
//设置窗体透明
this->setAttribute(Qt::WA_TranslucentBackground, true);
//设置无边框
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
QVBoxLayout* pMainLay = new QVBoxLayout(this);
CLoginRealWidget* pRealWidget = new CLoginRealWidget(this);
pMainLay->addWidget(pRealWidget);
pMainLay->setContentsMargins(30,30,30,30);
//setLayout(pMainLay);
//给顶层widget设置背景色,不然看不见,因为底层widget是透明的
pRealWidget->setStyleSheet("background-color:rgb(255,254,253)");
//创建一个阴影对象
QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect(this);
//设置阴影偏移量
shadow->setOffset(0, 0);
//设置阴影颜色
shadow->setColor(QColor("#00ff00"));
//设置阴影区域
shadow->setBlurRadius(30);
//给顶层widget设置阴影
pRealWidget->setGraphicsEffect(shadow);
}
CLoginDlg::~CLoginDlg()
{}
void CLoginDlg::mousePressEvent(QMouseEvent * event)
{
this->windowPos = this->pos();
this->mousePos = event->globalPosition();
this->dPos = mousePos - windowPos;
}
void CLoginDlg::mouseMoveEvent(QMouseEvent* event)
{
this->move((event->globalPosition() - this->dPos).toPoint());
}
-------------------------------------------
#pragma once
#include <QWidget>
class CLoginRealWidget : public QWidget
{
Q_OBJECT
public:
CLoginRealWidget(QWidget* p = nullptr);
~CLoginRealWidget();
private:
};
----------------------------------------
#include "CLoginRealWidget.h"
#include <QLabel>
#include <QLineEdit>
#include <QCheckBox>
#include <QPushButton>
#include <QHBoxLayout>
#include <QGridLayout>
CLoginRealWidget::CLoginRealWidget(QWidget* p)
:QWidget(p)
{
//禁止父窗口影响子窗口样式
setAttribute(Qt::WA_StyledBackground);
setWindowFlags(Qt::FramelessWindowHint);
//头像
QLabel* pImageLabel = new QLabel(this);
QPixmap pixmap(":/CLoginDlg/resource/user_image.png");
pImageLabel->setFixedSize(150, 150);
pImageLabel->setPixmap(pixmap);
pImageLabel->setScaledContents(true);
//用户名
QLineEdit* pUserNameLineEdit = new QLineEdit(this);
pUserNameLineEdit->setFixedSize(300, 50);
pUserNameLineEdit->setPlaceholderText(QStringLiteral("QQ号码/手机/邮箱"));
//密码
QLineEdit* pPasswordLineEdit = new QLineEdit(this);
pPasswordLineEdit->setFixedSize(300, 50);
pPasswordLineEdit->setPlaceholderText(QStringLiteral("密码"));
pPasswordLineEdit->setEchoMode(QLineEdit::Password);
QPushButton* pForgotButton = new QPushButton(this);
pForgotButton->setText(QStringLiteral("找回密码"));
pForgotButton->setFixedWidth(80);
QCheckBox* pRememberCheckBox = new QCheckBox(this);
pRememberCheckBox->setText(QStringLiteral("记住密码"));
QCheckBox* pAutoLoginCheckBox = new QCheckBox(this);
pAutoLoginCheckBox->setText(QStringLiteral("自动登录"));
QPushButton* pLoginButton = new QPushButton(this);
pLoginButton->setFixedHeight(48);
pLoginButton->setText(QStringLiteral("登录"));
QPushButton* pRegisterButton = new QPushButton(this);
pRegisterButton->setFixedHeight(48);
pRegisterButton->setText(QStringLiteral("注册账号"));
QHBoxLayout* pMainLay = new QHBoxLayout(this);
QSpacerItem* pHSpacer = new QSpacerItem(25, 20, QSizePolicy::Fixed, QSizePolicy::Fixed);
pMainLay->addSpacerItem(pHSpacer);
QGridLayout* pGridLayout = new QGridLayout(this);
// 头像 第0行,第0列开始,占3行1列
pGridLayout->addWidget(pImageLabel, 0, 0, 3, 1);
// 用户名输入框 第0行,第1列开始,占1行2列
pGridLayout->addWidget(pUserNameLineEdit, 0, 1, 1, 2);
// 密码输入框 第1行,第1列开始,占1行2列
pGridLayout->addWidget(pPasswordLineEdit, 1, 1, 1, 2);
// 忘记密码 第2行,第1列开始,占1行1列
pGridLayout->addWidget(pForgotButton, 2, 1, 1, 1);
// 记住密码 第2行,第2列开始,占1行1列 水平居中 垂直居中
pGridLayout->addWidget(pRememberCheckBox, 2, 2, 1, 1, Qt::AlignLeft | Qt::AlignVCenter);
// 自动登录 第2行,第2列开始,占1行1列 水平居右 垂直居中
pGridLayout->addWidget(pAutoLoginCheckBox, 2, 2, 1, 1, Qt::AlignRight | Qt::AlignVCenter);
// 登录按钮 第3行,第1列开始,占1行2列
pGridLayout->addWidget(pLoginButton, 3, 1, 1, 2);
// 注册按钮 第4行,第1列开始,占1行2列
pGridLayout->addWidget(pRegisterButton, 4, 1, 1, 2);
// 设置水平间距
pGridLayout->setHorizontalSpacing(10);
// 设置垂直间距
pGridLayout->setVerticalSpacing(10);
pMainLay->addLayout(pGridLayout);
pMainLay->addSpacerItem(pHSpacer);
pMainLay->setContentsMargins(5, 5, 5, 5);
setLayout(pMainLay);
}
CLoginRealWidget::~CLoginRealWidget()
{
}
ch3_8 实现圆角窗口
实现圆角窗口通常有两种方法:
1、重写paintEvent方法
2、qss样式表
#pragma once
#include <QtWidgets/QWidget>
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr);
~MainWidget();
private:
void paintEvent(QPaintEvent* event) override;
};
------------------------------------------------
#include "MainWidget.h"
#include <QPainter>
#include <QStyleOption>
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
resize(600, 400);
setAttribute(Qt::WA_TranslucentBackground);
setWindowFlags(Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint);
this->setStyleSheet("QWidget{background-color:#ffFFFF; \
border-top-left-radius:15px; \
border-bottom-right-radius:15px; \
}");
}
MainWidget::~MainWidget()
{}
//方法1重写paintEvent方法
//void MainWidget::paintEvent(QPaintEvent * event)
//{
// QPainter painter(this);
// painter.setRenderHint(QPainter::Antialiasing); //反锯齿
// painter.setBrush(QBrush(QColor(255, 255, 255))); //设置窗口颜色
// painter.setPen(Qt::transparent); //设置窗口边框颜色
// QRect rect = this->rect();
// painter.drawRoundedRect(rect, 15, 15); //设置窗口圆角 15px
//
//}
//方法2使用qss样式表,然后因为窗口被设置了透明,还需要重写paintEvent方法,否则无法显示窗口
void MainWidget::paintEvent(QPaintEvent* event)
{
QStyleOption opt;
opt.initFrom(this); //qt5中这个方法是init
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
方法1实现效果:

方法2实现效果:


1685

被折叠的 条评论
为什么被折叠?



