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


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Qt 中,可以通过自定义 QWidget 的 paintEvent() 函数来实现自定义标题栏。具体步骤如下: 1.创建一个新的 QWidget,用于作为自定义标题栏。 2.将 QWidget 的窗口标志设置为 Qt::WindowFlags(Qt::FramelessWindowHint),这样可以去掉默认的标题栏。 3.重写 QWidget 的 paintEvent() 函数,在该函数中绘制自定义标题栏。 4.将 QWidget 设置为 QMainWindow 的标题栏,即调用 QMainWindow 的 setWindowTitle() 函数,并将其参数设置为自定义标题栏的指针。 下面是一个简单的示例代码: ``` #include <QtWidgets> // 继承 QWidget,作为自定义标题栏 class CustomTitleBar : public QWidget { public: CustomTitleBar(QWidget *parent = nullptr) : QWidget(parent) { // 设置窗口标志 setWindowFlags(Qt::FramelessWindowHint); } protected: void paintEvent(QPaintEvent *) override { QPainter painter(this); painter.fillRect(rect(), Qt::blue); painter.drawText(rect(), Qt::AlignCenter, "Custom Title Bar"); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); QMainWindow mainWindow; // 设置主窗口标题 mainWindow.setWindowTitle("Main Window"); // 创建自定义标题栏 CustomTitleBar *titleBar = new CustomTitleBar(&mainWindow); // 设置自定义标题栏为主窗口的标题栏 mainWindow.setMenuWidget(titleBar); mainWindow.show(); return app.exec(); } ``` 运行该程序,可以看到自定义的蓝色标题栏。你可以根据自己的需要修改 paintEvent() 函数,来实现各种不同样式的标题栏
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值