自定义标题栏
功能点
1.标题栏中最外层布局器使用水平布局器。
2.导航按钮、工具按钮和窗口功能按钮都是用水平布局器,边距和间隔可根据实际情况设置。
3.编写 QSS 样式,并将样式设置到窗口控件中。
4.实现最小化、最大化和关闭窗口按钮功能。
5.实现鼠标双击标题栏切换窗口状态,最大化状态时切换至正常状态,正常状态切换至最大化状态。
6.鼠标拖动标题栏可在屏幕中移动窗口。
7.鼠标拖动窗体切换窗口状态,拖动至屏幕顶部切换至最大化状态,拖动离开屏幕顶部切换至正常状态。
源代码
JTitleBar .h
#ifndef JTITLEBAR_H
#define JTITLEBAR_H
#include <QWidget>
#include <QMouseEvent>
#include "jnavibutton.h"
namespace Ui {
class JTitleBar;
}
class JTitleBar : public QWidget
{
Q_OBJECT
public:
explicit JTitleBar(QWidget *parent = 0);
~JTitleBar();
enum WINSTATUS {NORMAL, MAXIMIZED, MINIMIZED};
Q_ENUMS(WINSTATUS)
void setTitleHeight(int height);
public Q_SLOTS:
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
Q_SIGNALS:
void nbtnTab1_clicked();
void nbtnTab2_clicked();
void nbtnTab3_clicked();
void configWin_clicked();
void changeSkin_clicked();
private:
void winStatus_changed();
private:
Ui::JTitleBar *ui;
private:
QList<JNaviButton*> m_listNaviButtons;
QList<QPushButton*> m_listToolButtons;
QList<QPushButton*> m_listWinButtons;
int m_titleHeight;
QPoint m_startPos;
bool m_bLeftButtonPressed;
WINSTATUS m_winStatus;
bool m_bDragMax;
};
#endif // JTITLEBAR_H
.cpp
#include "jtitlebar.h"
#include "ui_jtitlebar.h"
#include <QHBoxLayout>
JTitleBar::JTitleBar(QWidget *parent) :
QWidget(parent),
ui(new Ui::JTitleBar),
m_titleHeight(30),
m_bLeftButtonPressed(false),
m_winStatus(NORMAL),
m_bDragMax(false)
{
ui->setupUi(this);
QHBoxLayout *ui_hLayNaviButton = new QHBoxLayout;
ui_hLayNaviButton->addWidget(ui->nbtnTab1);
ui_hLayNaviButton->addWidget(ui->nbtnTab2);
ui_hLayNaviButton->addWidget(ui->nbtnTab3);
ui_hLayNaviButton->addStretch();
ui_hLayNaviButton->setContentsMargins(QMargins(0,0,0,0));
ui_hLayNaviButton->setSpacing(0);
ui->nbtnTab1->setChecked(true);
ui->nbtnTab1->setText(QStringLiteral("Tab1"));
ui->nbtnTab2->setText(QStringLiteral("Tab2"));
ui->nbtnTab3->setText(QStringLiteral("Tab3"));
connect(ui->nbtnTab1, &JNaviButton::clicked, [=](){ emit nbtnTab1_clicked(); });
connect(ui->nbtnTab2, &JNaviButton::clicked, [=](){ emit nbtnTab2_clicked(); });
connect(ui->nbtnTab3, &JNaviButton::clicked, [=](){ emit nbtnTab3_clicked(); });
m_listNaviButtons << ui->nbtnTab1 << ui->nbtnTab2 << ui->nbtnTab3;
ui->nbtnTab1->setNormalIcon(QPixmap(":/icon/icon/tab1.png"));
ui->nbtnTab1->setHoverIcon(QPixmap(":/icon/icon/tab1-hover.png"));
ui->nbtnTab1->setCheckedIcon(QPixmap(":/icon/icon/tab1-hover.png"));
ui->nbtnTab2->setNormalIcon(QPixmap(":/icon/icon/tab2.png"));
ui->nbtnTab2->setHoverIcon(QPixmap(":/icon/icon/tab2-hover.png"));
ui->nbtnTab2->setCheckedIcon(QPixmap(":/icon/icon/tab2-hover.png"));
ui->nbtnTab3->setNormalIcon(QPixmap(":/icon/icon/tab3.png"));
ui->nbtnTab3->setHoverIcon(QPixmap(":/icon/icon/tab3-hover.png"));
ui->nbtnTab3->setCheckedIcon(QPixmap(":/icon/icon/tab3-hover.png"));
for(auto btn : m_listNaviButtons) {
btn->setShowIcon(true);// 设置导航按钮显示图标
btn->setNormalBgColor(QColor(50, 57, 76, 0));
btn->setHoverBgColor(QColor(0, 0, 0, 50));
btn->setCheckedBgColor(QColor(0, 0, 0, 100));
btn->setNormalTextColor(QColor(210, 210, 215));
btn->setHoverTextColor(QColor(255, 255, 255));
btn->setCheckedTextColor(QColor(255, 255, 255));
btn->setIconSpace(20);// 设置图标左侧边距
btn->setPaddingLeft(30);// 设置文字左侧边距
}
QHBoxLayout *ui_hlayToolButton = new QHBoxLayout;
ui_hlayToolButton->addWidget(ui->btnProject);
ui_hlayToolButton->addWidget(ui->btnEdit);
ui_hlayToolButton->addWidget(ui->btnSetting);
ui_hlayToolButton->addWidget(ui->btnAbout);
QMargins margin = ui_hlayToolButton->contentsMargins();
margin.setRight(margin.right() + 10);
ui_hlayToolButton->setContentsMargins(margin);
m_listToolButtons << ui->btnProject << ui->btnEdit << ui->btnSetting << ui->btnAbout;
QHBoxLayout *ui_hlayWinButton = new QHBoxLayout;
ui_hlayWinButton->addWidget(ui->btnSkin);
ui_hlayWinButton->addWidget(ui->btnMin);
ui_hlayWinButton->addWidget(ui->btnMax);
ui_hlayWinButton->addWidget(ui->btnClose);
ui_hlayWinButton->setSpacing(0);
margin = ui_hlayWinButton->contentsMargins();
margin.setLeft(margin.left() + 10);
margin.setRight(margin.right() + 10);
ui_hlayWinButton->setContentsMargins(margin);
connect(ui->btnSetting, &QPushButton::clicked, [=](){ emit configWin_clicked(); });
connect(ui->btnSkin, &QPushButton::clicked, [=](){ emit changeSkin_clicked(); });
connect(ui->btnMin, &QPushButton::clicked, this, [=](){ parentWidget()->showMinimized(); });
connect(ui->btnMax, &QPushButton::clicked, [=](){ winStatus_changed(); });
connect(ui->btnClose, &QPushButton::clicked, [=](){ parentWidget()->close(); });
m_listWinButtons << ui->btnSkin << ui->btnMin << ui->btnMax << ui->btnClose;
QHBoxLayout *ui_hlayWindow = new QHBoxLayout;
ui_hlayWindow->addWidget(ui->btnLogo); // 添加 LOGO 按钮
ui_hlayWindow->addLayout(ui_hLayNaviButton);// 添加导航按钮所在布局器
ui_hlayWindow->addStretch(); // 添加一个弹簧
ui_hlayWindow->addLayout(ui_hlayToolButton);// 添加工具按钮所在布局器
ui_hlayWindow->addWidget(ui->frameLine); // 添加竖线
ui_hlayWindow->addLayout(ui_hlayWinButton);// 添加窗口功能按钮所在布局器
ui->btnLogo->setMinimumWidth(180); // 为 LOGO 按钮设置最小宽度
ui->frameLine->setFixedSize(1, 20); // 将竖线的尺寸设为固定值
ui_hlayWindow->setContentsMargins(QMargins(0,0,0,0));
ui_hlayWindow->setSpacing(0);
setLayout(ui_hlayWindow);
setAttribute(Qt::WA_StyledBackground, true);
/*
QString style = "QWidget#JTitleBar{background: qlineargradient(x1:0,y1:0,x2:1,y2:0,stop:0 #313947,stop:1 #34375E);}"
"QPushButton{border: none;}"
"QPushButton#btnLogo{color:white;}"
"QPushButton#btnProject{image: url(:/icon/icon/project.png); color:white;}"
"QPushButton#btnProject:hover{image: url(:/icon/icon/project-hover.png);}"
"QPushButton#btnEdit{image: url(:/icon/icon/analysis.png); color:white;}"
"QPushButton#btnEdit:hover{image: url(:/icon/icon/analysis-hover.png);}"
"QPushButton#btnSetting{image: url(:/icon/icon/setting.png); color:white;}"
"QPushButton#btnSetting:hover{image: url(:/icon/icon/setting-hover.png);}"
"QPushButton#btnAbout{image: url(:/icon/icon/about.png);}"
"QPushButton#btnAbout:hover{image: url(:/icon/icon/about-hover.png);}"
"QPushButton#btnMin{image: url(:/icon/icon/min.png);}"
"QPushButton#btnMin:hover{image: url(:/icon/icon/min-hover.png);"
"background-color: red;}"
"QPushButton#btnMax{image: url(:/icon/icon/max.png);}"
"QPushButton#btnMax:hover{image: url(:/icon/icon/max-hover.png);"
"background-color: red;}"
"QPushButton#btnClose{image: url(:/icon/icon/close.png);}"
"QPushButton#btnClose:hover{image: url(:/icon/icon/close-hover.png);"
"background-color: red;}"
"QFrame#frameLine{background-color: black;}";
setStyleSheet(style);
*/
}
JTitleBar::~JTitleBar()
{
delete ui;
}
void JTitleBar::setTitleHeight(int height)
{
if(m_titleHeight != height) {
m_titleHeight = height;
setFixedHeight(m_titleHeight);
ui->btnLogo->setFixedHeight(m_titleHeight);
for(auto btn : m_listNaviButtons) {
btn->setFixedHeight(m_titleHeight);
// btn->setFixedWidth(m_titleHeight * 3);
btn->setTextAlign(JNaviButton::TextAlign_Center);
}
}
}
void JTitleBar::winStatus_changed()
{// 判断是鼠标左键
if(NORMAL == m_winStatus) {// 当前处于正常状态则切换至最大化状态
parentWidget()->setWindowState(Qt::WindowMaximized);
m_winStatus = MAXIMIZED;
return;
}
if(MAXIMIZED == m_winStatus){// 当前处于最大化状态则切换至正常状态
parentWidget()->setWindowState(Qt::WindowNoState);
m_winStatus = NORMAL;
return;
}
}
void JTitleBar::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
m_startPos = event->pos();
m_bLeftButtonPressed = true;
}
}
void JTitleBar::mouseReleaseEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
m_bDragMax = false;
m_bLeftButtonPressed = false;
}
}
void JTitleBar::mouseMoveEvent(QMouseEvent *event)
{
if(m_bLeftButtonPressed) {
if(m_bDragMax) {
return;
}
if(MAXIMIZED == m_winStatus){// 当前处于最大化状态时切换至正常状态
parentWidget()->setWindowState(Qt::WindowNoState);
m_winStatus = NORMAL;
// QPoint p = event->pos() - m_startPos;
// parentWidget()->move(parentWidget()->x() + p.x(), parentWidget()->y() + p.y());
}
else {
if(event->globalY() <= 2) {// 判断距离屏幕顶部,距离小于 2 时切换至最大化状态
parentWidget()->setWindowState(Qt::WindowMaximized);
m_winStatus = MAXIMIZED;
m_bDragMax = true;
return;
}
else {// 正常移动窗口
QPoint p = event->pos() - m_startPos;
parentWidget()->move(parentWidget()->x() + p.x(), parentWidget()->y() + p.y());
}
}
}
}
void JTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
winStatus_changed();
}
}