Qt自定义标题栏

news2024/10/5 14:35:34

一、创建项目

最终项目文件结构如下

 

 “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);  //更改标题栏大小
}

四、运行测试

可以显示标题内容和图标

双击标题栏,可以放大缩小,放大/还原图标样式会更改

左键按下标题栏,可以移动界面;当最大化时,界面会先还原再移动

鼠标停放在按键上,按键会变颜色

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/948869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

antd upload组件beforeUpload返回promise之后,获取的文件不是file类型导致上传失败

之前的beforeUpload直接返回一个false值 &#xff0c;文件是可以正常与服务端进行传输的 beforeUpload: (file) > {return false},但是这样并不能阻止文件上传&#xff0c;看了官方文档后&#xff0c;改用返回promise对象上传 beforeUpload: (file) > {console.log(-befo…

Primeng table filter 重置条件

我用一个overlayPanel装了p-table&#xff0c;里面有个count的filter&#xff0c;但是我设置值之后&#xff0c;让overlayPanel消失&#xff0c;再出现的时候&#xff0c;明明已经重新设置了表里面的数据和filter的变量值&#xff0c;但是上一次的条件仍然在,旁边的文字filter依…

openGauss本地Centos7.6单机安装和简单应用

openGauss本地Centos7.6单机安装和简单应用 openGauss基础环境配置openGauss安装openGauss使用测试openGauss常用命令 openGauss基础环境配置 在VMware Workstation中安装一台 centos7.6 内存&#xff1a;8GB&#xff0c;亲测4GB安装不够 磁盘&#xff1a;测试50GB-100GB够用 …

谈了千百遍的数据一致性

今天来说一个老生常谈的问题&#xff0c;来看一个实际案例&#xff1a; 现有业务中往往都会通过缓存来提高查询效率&#xff0c;降低数据库的压力&#xff0c;尤其是在分布式高并发场景下&#xff0c;大量的请求直接访问Mysql很容易造成性能问题。 有一天老板找到了你… 老板…

四川玖璨电子商务有限公司:开抖店怎么运营

开抖店是一种越来越流行的创业方式&#xff0c;在社交媒体平台上开店销售各种商品&#xff0c;比如服装、配饰、美妆和家居用品等等。对于新手来说&#xff0c;他们可能会很关心自己开抖店能够多久出单。虽然这个问题没有一个固定的答案&#xff0c;但是以下是一些关键的运营方…

一文讲透:低代码平台是什么?低代码平台应该如何挑选?

低代码平台是什么&#xff1f;低代码平台的边界在哪&#xff1f;低代码平台的优势&#xff1f;低代码平台哪个好用&#xff1f;2023年有哪些国内值得关注的低代码平台&#xff1f;本文将深入浅出的带大家了解低代码平台&#xff0c;并且为大家带来2023年国内最热六款低代码平台…

【MySQL系列】-ORDER BY……HAVING详解及limit

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

【ELK日志收集系统】

目录 一、概述 1.作用 2.为什么使用&#xff1f; 二、组件 1.elasticsearch 1.1 作用 1.2 特点 2.logstash 2.1 作用 2.2 工作过程 2.3 INPUT 2.4 FILETER 2.5 OUTPUTS 3.kibana 三、架构类型 1.ELK 2.ELKK 3.ELFK 4.ELFKK 四、案例 - 构建ELK集群 1.环境…

【行为树】py_trees 学习笔记

学习资料 《Introduction to behavior trees》 1. 概念说明 1.1 Action&#xff1a;pt.behaviour.Behaviour 在一个行为树中&#xff0c;Action 是一个叶节点&#xff08;Leaf Node&#xff09;&#xff0c;它实际执行某种行为或任务&#xff0c;并返回成功、失败或运行中的…

微服务·架构组件之注册与发现

引言 微服务架构在现代软件开发中越来越受欢迎&#xff0c;它通过将系统拆分为多个小型、自治的服务来提高可维护性、可扩展性和灵活性。然而随着服务数量的增多&#xff0c;服务之间的通信何发现变得更加复杂。本报告旨在深入探讨微服务中的注册与发现&#xff0c;介绍其背景…

使用rem + sass + 媒体查询 进行横竖屏适配移动端项目

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、 媒体查询&#xff08;Media Query&#xff09;1.简单了解2.简单例子3. 语法&#xff08;1&#xff09;媒体类型&#xff08;mediatype &#xff09;&#xff0…

【黑科技】游戏开发程序员必备工具【一】

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;效率…

MongoDB实验——在Java应用程序中操作 MongoDB 数据

在Java应用程序中操作 MongoDB 数据 1. 启动MongoDB Shell 2. 切换到admin数据库&#xff0c;使用root账户 3.开启Eclipse&#xff0c;创建Java Project项目&#xff0c;命名为MongoJava File --> New --> Java Project 4.在MongoJava项目下新建包&#xff0c;包名为mo…

【SpringBoot系列】 测试框架之@SpringBootTest的使用

SpringBootTest的详细介绍 SpringBootTest 是 Spring Boot 测试框架中的注解&#xff0c;用于标识一个测试类&#xff0c;以指示该类是一个 Spring Boot 应用程序的测试类。它允许你在测试环境中加载整个 Spring Boot 应用程序上下文&#xff0c;测试应用程序的各种组件、服务…

如何备考 PMP 考试?

一、PMP学习7步走攻略 ​1、熟悉考试大纲&#xff1a; PMP考试大纲是备考的基础&#xff0c;考生需要详细熟悉考试大纲&#xff0c;了解各个知识领域的重点和难点。 2、制定学习计划&#xff1a; 根据考试大纲和个人情况&#xff0c;制定学习计划&#xff0c;合理分配学习时间…

OA项目之我的会议(查询会议排座送审)

目录 会议查询 会议排座 会议送审 思路&#xff1a; 关键性会议SQL的编写后台实现前台实现 会议查询 MeetingInfoDao.java // 通用的会议查询SQL语句&#xff0c;包含会议信息表数据&#xff0c;主持人姓名、审批人姓名、会议状态private String getSQL() {return "…

android:新建工程文件介绍

一、前言当我们新建一个app时会呈现出固定的工程文件&#xff0c;这篇文章介绍新建工程里的文件。 二、介绍 Structure:就是你选择哪个页面就会显示那个页面的结构&#xff0c;就比如说我选择的是MainActivity他就会显示这个页面所使用的方法。 1-2&#xff1a;是android自动生…

【ESP32】解决接串口助手时,无法启动问题

本文主要记录ESP32正常烧录程序后&#xff0c;接上串口助手就无法启动&#xff0c;报错 waiting for download&#xff0c;拔掉串口助手后&#xff0c;程序可以正常启动 &#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是喜欢记录零碎知识点的…

小程序隐私保护授权处理方式之弹窗组件

欢迎点击关注-前端面试进阶指南&#xff1a;前端登顶之巅-最全面的前端知识点梳理总结 *分享一个使用比较久的&#x1fa9c; 小程序隐私保护授权弹窗组件 调用wx.getUserProfile进行授权时&#xff0c;返回错误信息&#xff1a;{errMsg: “getUserProfile:fail api scope is…

nvm和volta对node版本控制的区别

前言——我们做前端开发的都会需要node.js环境&#xff0c;我们直接安装指定的版本可以么&#xff1f;可以&#xff0c;只不过在需要换版本的时候还得卸载重新装。那有工具可以帮助我们不用卸载就更改node版本么&#xff1f;有啊&#xff0c;nvm就可以。那又有没有什么工具不用…