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


    自定义标题栏

    功能点

    1.标题栏中最外层布局器使用水平布局器。
    2.导航按钮、工具按钮和窗口功能按钮都是用水平布局器,边距和间隔可根据实际情况设置。
    3.编写 QSS 样式,并将样式设置到窗口控件中。
    4.实现最小化、最大化和关闭窗口按钮功能。
    5.实现鼠标双击标题栏切换窗口状态,最大化状态时切换至正常状态,正常状态切换至最大化状态。
    6.鼠标拖动标题栏可在屏幕中移动窗口。
    7.鼠标拖动窗体切换窗口状态,拖动至屏幕顶部切换至最大化状态,拖动离开屏幕顶部切换至正常状态。

    在这里插入图片描述

    源代码

    JTitleBar .h

    #ifndef JTITLEBAR_H
    #define JTITLEBAR_H
    
    #include 
    #include 
    #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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    .cpp

    #include "jtitlebar.h"
    #include "ui_jtitlebar.h"
    #include 
    
    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();
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
  • 相关阅读:
    差分进化算法解析:Scala实现详细指南及其在优化问题中的应用
    使用Hot Chocolate和.NET 6构建GraphQL应用(8) —— 实现Mutate添加数据
    FreeMarkerViewResolver类简介说明
    Android修行手册 - TabLayout全解析(下)-监听和示例
    MERLIN-AToolfor Multi-party Privacy-preserving Record Linkage论文总结
    hive acid及事务表踩坑学习实录
    React@16.x(29)useRef
    搭建rtmp流媒体服务器的步骤
    在设计web页面时,为移动端设计一套页面,PC端设计一套页面,并且能自动根据设备类型来选择是用移动端的页面还是PC端的页面。
    LightDB数据库中的模式
  • 原文地址:https://blog.csdn.net/simple_core/article/details/134422980