Qt高级--(2)自定义标题栏

自定义标题栏

功能点

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();
    }
}


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

可信联邦学习冬令营·成都开营,产学研共促AI人才培养

近年来&#xff0c;国家对于人工智能和数据安全的重视程度不断加强。国务院《新一代人工智能发展规划》中明确提出了加强人工智能领域的基础研究、培养高素质人才、促进产业融合等方面的要求。联邦学习是人工智能和隐私计算核心技术之一&#xff0c;以“数据不动模型动&#xf…

Tomcat web.xml文件中的mime-mapping

在Tomcat安装目录的conf/web.xml文件中&#xff0c;定义了大量的<mime-mapping>元素&#xff0c;例如&#xff1a; 其中<extension>指定了文件的扩展名&#xff0c;<mime-type>指定了mime类型&#xff0c;放在<mime-mapping>元素中&#xff0c;就是将…

APIcloud 【现已更名 用友开发中心】 iOS发版 应用程序请求用户同意访问相机和照片,但没有在目的字符串中充分说明相机和照片的使用。

iOS 审核时 提示 首次安装软件 获取相机 相册 提示信息 怎么修改 我们注意到你的应用程序请求用户同意访问相机和照片&#xff0c;但没有在目的字符串中充分说明相机和照片的使用。 为了解决这个问题&#xff0c;修改应用信息中的目的字符串是合适的。相机和照片的Plist文件&a…

layui表头多出一列(已解决)

问题描述 &#xff1a;layui表头多出来一列&#xff0c;但是表体没有内容&#xff0c;很影响美观。 好像是原本的表格有滚轮&#xff0c;我操作放大之后滚轮没有了&#xff0c;但是滚轮自带的表头样式还在&#xff0c; 之后手动把这个样式隐藏掉了&#xff0c;代码如下&#xf…

iceoryx(冰羚)-简介

概要 RouDi RouDi是Routing and Discovery的缩写。RouDi负责通信设置&#xff0c;但实际上并不参与发布者与订阅者或客户端与服务器之间的通信。鲁迪可以被认为是iceoryx的总机操作员。它的另一个主要任务是设置共享内存&#xff0c;应用程序使用共享内存交换有效负载数据。Ro…

操作系统(五)文件系统和I/O系统

文章目录 前言文件系统文件系统和文件文件描述符目录、文件别名和文件系统分层文件系统目录实现文件别名名字解析&#xff08;路径遍历&#xff09;文件系统挂载文件系统种类 虚拟文件系统文件缓存和打开文件打开文件 文件分配空闲空间管理和冗余磁盘阵列RAID空闲空间管理冗余磁…

JJJ:python学习笔记

p4 没有编译的过程 源码和输入得到输出 静态语言&#xff1a;编译型 脚本语言&#xff1a;解释型 p5 又叫做胶水语言 p7 p8 p10

RHCE8 资料整理(六)

RHCE8 资料整理 第 6 篇 软件管理第 23 章 用rpm管理软件23.1 rpm查询23.2 rpm卸载23.3 软件包升级23.4 rpm验证 第 24 章 用yum/dnf管理软件包24.1 yum架构介绍24.2 用光盘搭建yum源24.3 创建私有仓库24.4 yum客户端配置24.5 yum基本使用24.5.1 查询24.5.2 安装与卸载24.5.3 下…

Navicat Premium 16,无限重置试用14天

打开注册表编辑器 红箭头所指方向每个系统判别不一样 如何判别呢&#xff1f;一个个点开看底下是不是info&#xff0c;如果是那么把info文件夹删掉就可以了。

SecureCRT 9.4.2 for Mac

SecureCRT是一款由VanDyke Software公司开发的终端仿真软件&#xff0c;它提供了类似于Telnet和SSH等协议的远程访问功能。SecureCRT专门为网络管理员、系统管理员和其他需要保密访问网络设备的用户设计。 SecureCRT具有以下特点&#xff1a; 安全性&#xff1a;SecureCRT支持…

OpenHarmony应用开发入门教程(一、开篇)

前言 华为正式宣布2024年发布的华为鸿蒙OS Next版将不再兼容安卓系统。这一重大改变&#xff0c;预示着华为鸿蒙OS即将进入一个全新的阶段。 都说科技无国界&#xff0c;这是骗人的鬼话。谷歌的安卓12.0系统早已发布&#xff0c;但是自从受到美影响&#xff0c;谷歌就拒绝再向…

FPGA模块——IIC协议(FPGA做主机操作24C64)

FPGA模块——IIC协议&#xff08;FPGA做主机操作24C64&#xff09; EEPROM&#xff08;24C64&#xff09;向器件写数据时序向器件读数据时序 IIC协议FPGA主机代码IIC驱动 EEPROM&#xff08;24C64&#xff09; 掉电不丢失&#xff0c;采用固定的读写协议。数据的稳定性和可重复…

vite动态配置svg图标及其他方式集合

文章目录 前言使用vite-plugin-svg-icons动态配置安装插件引入图标下载新建组件svg-icon.vue使用 使用vue组件动态配置总结如有启发&#xff0c;可点赞收藏哟~ 前言 在配置化的情况下&#xff0c;图标配置也显得极为重要的 使用vite-plugin-svg-icons动态配置 参考vite-plugin…

入职算法工程师后敲的非常有趣使用的小工具

NOTE&#xff1a;代码仅用来参考&#xff0c;没时间解释啦&#xff01; &#x1f349;一、自动从数据库从抽取数据。 在某台服务器中&#xff0c;从存放数据集的数据库自动抽取标注好的数据标签&#xff0c;这一步操作有什么用呢&#xff1f;当我们发现我们数据不均衡的时候&a…

【Linux】vscode远程连接ubuntu失败

VSCode远程连接ubuntu服务器 这部分网上有很多&#xff0c;都烂大街了&#xff0c;自己搜吧。给个参考连接&#xff1a;VSCode远程连接ubuntu服务器 注意&#xff0c;这里我提前设置了免密登录。至于怎么设置远程免密登录&#xff0c;可以看其它帖子&#xff0c;比如这个。 …

FastAdmin表格顶部增加toolbar按钮

效果入下图&#xff0c;在表格顶部增加一个自定义按钮&#xff0c;点击确认后请求服务器接口 表格对应的index.html中 <div class"panel-body"><div id"myTabContent" class"tab-content"><div class"tab-pane fade active …

JVM GC 调优命令看这一篇就够了

JVM GC 调优命令看这一篇就够了 2023-11-11 23:27IT果果日记 jstat 可用于统计内存分配速率、GC次数&#xff0c;GC耗时 jstat常用命令格式 jstat -gc <pid> <统计间隔时间> <统计次数> 例如&#xff1a;jstat -gc 6 1000 10 &#xff0c;统计pid6的进…

【设计一个缓存--针对各种类型的缓存】

设计一个缓存--针对各种类型的缓存 1. 设计顶层接口2. 设计抽象类 -- AbstractCacheManager3. 具体子类3.1 -- AlertRuleItemExpCacheManager3.2 -- AlertRuleItemSrcCacheManager 4. 类图关系 1. 设计顶层接口 // 定义为一个泛型接口,提供给抽象类使用 public interface Cach…

技术管理责任制度《三》

为了加强新时期科技档案的保密工作&#xff0c;确保档案在保管、利用、复制、销毁过程中的保密工作&#xff0c;特规定如下&#xff1a; 彩虹图纸管理软件_图纸管理系统_图纸文档管理软件系统_彩虹EDM【官网】 1、档案员要认真学习和严格执行国家有关安全、保密制度规定&#…

【java学习—十四】反射获取类的父类、接口、构造方法、方法(3)

文章目录 1. 通过反射获取一个类的父类和接口2. 反射获取一个类的构造方法3. 反射获取全部构造器4. 通过反射创建一个对象5. 反射机制获取类的方法 1. 通过反射获取一个类的父类和接口 使用反射可以取得&#xff1a; 实现的全部接口 public Class<?>[] getInterfaces(…