一、创建项目
最终项目文件结构如下
“iconfont.tff”的使用方式见如下博客,用于更改图标颜色
Qt更改图标颜色_怎么追摩羯座的博客-CSDN博客
二、MyTitleBar.pro
#-------------------------------------------------
#
# Project created by QtCreator 2023-08-28T09:46:06
#
#-------------------------------------------------QT += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = 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.0CONFIG += c++11SOURCES += \main.cpp \mainwindow.cpp \titlebar.cppHEADERS += \mainwindow.h \titlebar.hFORMS += \mainwindow.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetRESOURCES += \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_fontColorm_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_OBJECTpublic: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); //更改标题栏大小
}
四、运行测试
可以显示标题内容和图标
双击标题栏,可以放大缩小,放大/还原图标样式会更改
左键按下标题栏,可以移动界面;当最大化时,界面会先还原再移动
鼠标停放在按键上,按键会变颜色