一、创建项目
最终项目文件结构如下
“iconfont.tff”的使用方式见如下博客,用于更改图标颜色
Qt更改图标颜色_怎么追摩羯座的博客-CSDN博客
二、MyTitleBar.pro
#-------------------------------------------------
#
# Project created by QtCreator 2023-08-28T09:46:06
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = MyTitleBar
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++11
SOURCES += \
main.cpp \
mainwindow.cpp \
titlebar.cpp
HEADERS += \
mainwindow.h \
titlebar.h
FORMS += \
mainwindow.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
file.qrc
二、创建自定义标题类TitleBar
titlebar.h代码如下
/**
* @brief TitleBar 自定义标题栏
*/
#ifndef TITLEBAR_H
#define TITLEBAR_H
#include <QWidget>
class QLabel;
class QPushButton;
class TitleBar : public QWidget
{
Q_OBJECT
public:
explicit TitleBar(QWidget *parent = nullptr);
~TitleBar();
void setColor(QString backgroundColor, QString fontColor, QString selectedFontColor); //设置颜色
protected:
//界面拖动
void mousePressEvent(QMouseEvent* event); //鼠标按下
void mouseMoveEvent(QMouseEvent* event); //鼠标移动
void mouseReleaseEvent(QMouseEvent* event); //鼠标抬起
void mouseDoubleClickEvent(QMouseEvent* event); //双击标题栏进行界面的最大化/还原
bool eventFilter(QObject *obj, QEvent *event); //事件过滤器
private slots:
void onClicked(); //进行最小化、最大化/还原、关闭操作
void updateMaximize(); //最大化/还原
private:
QLabel* m_iconLabel; //显示图标
QLabel* m_titleLabel; //显示标题
QPushButton* m_minimizeButton; //最小化按键
QPushButton* m_maximizeButton; //最大化/还原按键
QPushButton* m_closeButton; //关闭按键
QPoint m_mousePosition; //鼠标按下时的位置
bool m_isMousePressed; //鼠标是否摁下
QString m_backgroundColor; //背景色
QString m_fontColor; //字体色
QString m_selectedFontColor; //被选中的字体色
};
#endif // TITLEBAR_H
titlebar.cpp代码如下
#include "titlebar.h"
#include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QFontDatabase>
#include <QApplication>
TitleBar::TitleBar(QWidget *parent)
: QWidget(parent)
{
setFixedHeight(30);
//控件初始化
m_iconLabel = new QLabel(this);
m_titleLabel = new QLabel(this);
m_minimizeButton = new QPushButton(this);
m_maximizeButton = new QPushButton(this);
m_closeButton = new QPushButton(this);
//图片自适应控件大小
m_iconLabel->setFixedSize(20, 20);
m_iconLabel->setScaledContents(true);
//设置控件在布局(layout)里面的大小变化的属性
m_titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
//设置控件的最小大小和最大大小
m_minimizeButton->setFixedSize(30, 25);
m_maximizeButton->setFixedSize(30, 25);
m_closeButton->setFixedSize(30, 25);
//设置控件唯一标识符
m_titleLabel->setObjectName("whiteLabel");
m_minimizeButton->setObjectName("minimizeButton");
m_maximizeButton->setObjectName("maximizeButton");
m_closeButton->setObjectName("closeButton");
//设置图标
int fontId = QFontDatabase::addApplicationFont(":/font/iconfont.ttf");
QString fontName = QFontDatabase::applicationFontFamilies(fontId).at(0);
QFont iconFont = QFont(fontName);
iconFont.setPixelSize(17);
m_minimizeButton->setFont(iconFont);
m_minimizeButton->setText(QChar(0xe61b));
m_minimizeButton->setToolTip(tr("最小化"));
m_minimizeButton->installEventFilter(this);
m_maximizeButton->setFont(iconFont);
m_maximizeButton->setText(QChar(0xe692));
m_maximizeButton->setToolTip(tr("向下还原"));
m_maximizeButton->installEventFilter(this);
m_closeButton->setFont(iconFont);
m_closeButton->setText(QChar(0xe723));
m_closeButton->setToolTip(tr("关闭"));
m_closeButton->installEventFilter(this);
//控件布局
QHBoxLayout *pLayout = new QHBoxLayout(this);
pLayout->addWidget(m_iconLabel);
pLayout->addSpacing(5);
pLayout->addWidget(m_titleLabel);
pLayout->addWidget(m_minimizeButton);
pLayout->addWidget(m_maximizeButton);
pLayout->addWidget(m_closeButton);
pLayout->setSpacing(0);
pLayout->setContentsMargins(5, 0, 5, 0);
setLayout(pLayout);
//信号槽绑定
connect(m_minimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
connect(m_maximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
connect(m_closeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
}
TitleBar::~TitleBar()
{
}
/**
* @brief MainWindow::mousePressEvent 鼠标双击:界面最大化或还原
* @param event 鼠标事件
*/
void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_UNUSED(event);
emit m_maximizeButton->clicked();
}
/**
* @brief MainWindow::mousePressEvent 鼠标按下:准备移动
* @param event 鼠标事件
*/
void TitleBar::mousePressEvent(QMouseEvent *event)
{
m_mousePosition = event->pos();
m_isMousePressed = true;
}
/**
* @brief MainWindow::mousePressEvent 鼠标移动
* @param event 鼠标事件
*/
void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
if (m_isMousePressed == true )
{
QWidget *pWindow = this->window();
if(pWindow->isMaximized()) //界面最大时,先还原再移动
{
pWindow->showNormal();
//防止鼠标指针在界面之外
m_mousePosition = QPoint(200, 10);
pWindow->move(event->globalPos().x() - 200, event->globalPos().y());
}
else
{
QPoint movePot = event->globalPos() - m_mousePosition;
pWindow->move(movePot);
}
}
}
/**
* @brief MainWindow::mousePressEvent 鼠标抬起:移动结束
* @param event 鼠标事件
*/
void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event);
m_isMousePressed = false;
}
/**
* @brief TitleBar::eventFilter 事件过滤器
* @param obj 过滤对象
* @param event 事件
* @return
*/
bool TitleBar::eventFilter(QObject *obj, QEvent *event)
{
switch(event->type())
{
case QEvent::WindowTitleChange: //更改标题显示内容
{
QWidget *pWidget = qobject_cast<QWidget *>(obj);
if(pWidget)
{
m_titleLabel->setText(pWidget->windowTitle());
}
}
break;
case QEvent::WindowIconChange: //更改图标
{
QWidget *pWidget = qobject_cast<QWidget *>(obj);
if(pWidget)
{
QIcon icon = pWidget->windowIcon();
m_iconLabel->setPixmap(icon.pixmap(m_iconLabel->size()));
}
}
break;
case QEvent::WindowStateChange:
case QEvent::Resize:
updateMaximize(); //最大化/还原
break;
case QEvent::Enter: //鼠标悬停在控件上,控件变色
{
if(obj == m_minimizeButton)
{
m_minimizeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_selectedFontColor));
}
else if(obj == m_closeButton)
{
m_closeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_selectedFontColor));
}
else if(obj == m_maximizeButton)
{
m_maximizeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_selectedFontColor));
}
}
break;
case QEvent::Leave: //鼠标离开控件,颜色恢复
{
if(obj == m_minimizeButton)
{
m_minimizeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_fontColor));
}
else if(obj == m_closeButton)
{
m_closeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_fontColor));
}
else if(obj == m_maximizeButton)
{
m_maximizeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_fontColor));
}
}
break;
default:
break;
}
return QWidget::eventFilter(obj, event);
}
/**
* @brief TitleBar::onClicked 进行最小化、最大化/还原、关闭操作
*/
void TitleBar::onClicked()
{
QPushButton *pButton = qobject_cast<QPushButton *>(sender());
QWidget *pWindow = this->window();
if (pWindow->isTopLevel())
{
if(pButton == m_minimizeButton) //最小化
{
pWindow->showMinimized();
}
else if (pButton == m_maximizeButton) //最大化、还原
{
pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
}
else if (pButton == m_closeButton) //关闭
{
pWindow->close();
}
}
}
/**
* @brief TitleBar::updateMaximize 最大化/还原时,更改图标样式
*/
void TitleBar::updateMaximize()
{
QWidget *pWindow = this->window();
if(pWindow->isTopLevel())
{
bool bMaximize = pWindow->isMaximized();
if(bMaximize)
{
m_maximizeButton->setToolTip(tr("向下还原"));
m_maximizeButton->setProperty("maximizeProperty", "向下还原");
m_maximizeButton->setText(QChar(0xe692));
}
else
{
m_maximizeButton->setProperty("maximizeProperty", "最大化");
m_maximizeButton->setToolTip(tr("最大化"));
m_maximizeButton->setText(QChar(0xe65d));
}
m_maximizeButton->setStyle(QApplication::style());
}
}
/**
* @brief TitleBar::setColor 更改颜色
* @param backgroundColor 背景色
* @param fontColor 控件颜色/字体颜色
* @param selectedFontColor 鼠标悬停在控件上时的颜色
*/
void TitleBar::setColor(QString backgroundColor, QString fontColor, QString selectedFontColor)
{
m_backgroundColor = backgroundColor;
m_fontColor = fontColor;
m_selectedFontColor = selectedFontColor;
//按键背景透明,图标颜色为m_fontColor
m_minimizeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_fontColor));
m_maximizeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_fontColor));
m_closeButton->setStyleSheet(QString("QPushButton{background-color:rgba(0,0,0,0);color:%1}").arg(m_fontColor));
m_titleLabel->setStyleSheet(QString("QLabel{color:%1}").arg(m_fontColor));
}
三、使用
mainwindow.h代码如下
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "titlebar.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void resizeEvent(QResizeEvent *event);
private:
Ui::MainWindow *ui;
TitleBar* m_titleBar; //自定义标题栏
};
#endif // MAINWINDOW_H
mainwindow.cpp代码如下
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_titleBar = new TitleBar(this);
m_titleBar->resize(this->width(), 30);
m_titleBar->move(0, 0);
installEventFilter(m_titleBar);
setWindowTitle("Custom Window"); //设置标题内容
setWindowIcon(QIcon(":/font/capricorn.png")); //设置图标
//第一个是去掉原边框及标题栏,第二个是保留最小化及还原功能,主要是为了还原,最小化下面实现了
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
ui->menuBar->setVisible(false); //隐藏菜单栏
ui->mainToolBar->setVisible(false); //隐藏工具栏
//ui->statusBar->setVisible(false); //隐藏状态栏
this->showMaximized(); //最大化显示
QString backgroundColor = "black"; //背景色
QString fontColor = "white"; //字体色
QString selectedFontColor = "red"; //被选中的字体色
//渐变背景
this->setStyleSheet(QString("QMainWindow#MainWindow{background-color:qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 %1, stop:1 %2);}")
.arg(backgroundColor).arg(fontColor));
//设置标题栏颜色
m_titleBar->setColor(backgroundColor, fontColor, selectedFontColor);
}
MainWindow::~MainWindow()
{
delete ui;
}
/**
* @brief MainWindow::resizeEvent 当界面大小改变时更改标题栏大小
* @param event
*/
void MainWindow::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
m_titleBar->resize(this->width(), 30); //更改标题栏大小
}
四、运行测试
可以显示标题内容和图标
双击标题栏,可以放大缩小,放大/还原图标样式会更改
左键按下标题栏,可以移动界面;当最大化时,界面会先还原再移动
鼠标停放在按键上,按键会变颜色