前言

使用Qt自带的标题栏可能没有办法适合我们的需求,例如标题栏的颜色,标题栏的宽度、高度,标题栏的放大、缩小、还原、关闭按钮等都没有办法发生改变。因为默认的标题栏是和操作系统相关的、它会根据操作系统的变化而发生变化,在Window上不同风格的主题,在Qt程序产生的标题栏也会发生相应的变化,在linux上也是如此。而自定义标题栏则不会这样,颜色,大小,按钮图标这完全有我们来控制,来达到标题栏的自由性和统一性。

/*mytitilebar.h*/
#ifndef MYTITLEBAR_H
#define MYTITLEBAR_H

#include <QWidget>
#include <QToolButton>
#include <QPixmap>
#include <QLabel>
#include <QColor>
#include <QPainter>
#include <QHBoxLayout>
#include <QMouseEvent>
#include <QStyle>
#include <QLabel>
#include <QtDebug>
#include <QLinearGradient>

#define  ICON_WIDTH     20
#define  ICON_HEIGHT    20
#define  BUTTON_WIDTH   30
#define  BUTTON_HEIGHT  30
#define  TITLE_HEIGHT   30

class myTitleBar : public QWidget
{
    Q_OBJECT
public:
    myTitleBar(QWidget *parent);
    void SetTitleBackground(QColor Color); // 供外部调用设置标题栏背景
    void SetTitleContent(QString content); // ……………设置标题栏内容
    void SetTitleIcon(QString iconPath);   // ……………设置标题栏图标

public slots:
    void ShowSmall();      //槽函数,最小化
    void ShowMaxRestore(); // 槽函数 ,最大化或者还原
protected:
    void mousePressEvent(QMouseEvent *e);           // 鼠标点击事件
    void mouseMoveEvent(QMouseEvent *e);            // 鼠标移动事件
    void mouseDoubleClickEvent(QMouseEvent *e);     // 鼠标双击事件

private:

    void InitTitleBar();                 // 初始化标题栏
    void paintEvent(QPaintEvent *event); // 重载绘画函数


    QToolButton *m_Minimize;             // 最小化按钮
    QToolButton *m_Maximize;             // 最大化按钮
    QToolButton *m_Close;                // 关闭按钮

    QPixmap *m_RestorePix;  // 还原按钮的图片
    QPixmap *m_MaxPix;      // 最大化按钮的图片
    QPixmap *m_MinPix;      // 最小化按钮的图片

    QPoint m_StartPos;      // 记录窗口开始的位置
    QPoint m_ClickPos;

    QLabel *m_TitleIcon;    // 标题栏图标
    QLabel *m_TitleConten;  // 标题栏标题
    QLabel m_TitleLabel;

    QColor m_ColorL;         // 标题栏渐变色
    QColor m_ColorR;         // 标题栏渐变色

    QWidget *m_Parent;       //父窗体

};

#endif // MYTITLEBAR_H
/*************************************************************************/
//File name:    mytitlebar.cpp
//Date:         2017.10.23
//Description:  自定义标题栏
/*************************************************************************/

#include "mytitlebar.h"

myTitleBar::myTitleBar(QWidget *parent):m_ColorL(QColor(0,0,0)),
m_ColorR(QColor(255,255,255)) // 初始化渐变色(白->黑渐变)
{

    this->setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);  // 隐藏默认的标题栏
    m_Parent = parent;       // 获取标题栏的父窗体,用来控制窗口放大,缩小,关闭等行为
    m_MaxNormal = false;     // 初始化窗口不是最大化状态
    InitTitleBar();          // 初始化标题栏

    // 连接标题栏三个按钮到相应的槽函数中
    connect(m_Close, SIGNAL( clicked() ), m_Parent, SLOT(close() ));
    connect(m_Minimize, SIGNAL( clicked() ), this, SLOT(ShowSmall() ) );
    connect(m_Maximize, SIGNAL( clicked() ), this, SLOT(ShowMaxRestore() ) );
}


void myTitleBar::InitTitleBar()
{

    m_Close= new QToolButton(this);                              // 关闭按钮
    m_ClosePix  = new QPixmap(":/icon/close.png");               // 关闭按钮图片
    m_Close->setIcon(*m_ClosePix);
    m_Close->setToolTip("关闭");                                   // 显示提示文字
    m_Close->setIconSize(QSize(ICON_WIDTH,ICON_HEIGHT));         // 设置图片的大小
    m_Close->setFixedSize(m_ClosePix->size());                   // 设置按钮大小为图片的大小
    m_Close->setStyleSheet("border-style:flat");                 // 设置按钮背景透明

    m_Maximize = new QToolButton(this);                          // 最大化按钮
    m_MaxPix  = new QPixmap(":/icon/scale.png");
    m_RestorePix  = new QPixmap(":/icon/scale.png");
    m_Maximize->setIcon(*m_MaxPix);
    m_Maximize->setToolTip("最大化");
    m_Maximize->setIconSize(QSize(ICON_WIDTH,ICON_HEIGHT));
    m_Maximize->setFixedSize(m_MaxPix->size());
    m_Maximize->setStyleSheet("border-style:flat");

    m_Minimize = new QToolButton(this);                         // 最小化按钮
    m_MinPix  = new QPixmap(":/icon/mi.png");
    m_Minimize->setIcon(*m_MinPix);
    m_Minimize->setToolTip("最小化");
    m_Minimize->setIconSize(QSize(ICON_WIDTH,ICON_HEIGHT));
    m_Minimize->setFixedSize(m_MinPix->size());
    m_Minimize->setStyleSheet("border-style:flat");

    m_TitleConten = new QLabel(this);                          // 标题栏文字
    QFont TitleFont; 
    TitleFont.setPointSize(12);
    m_TitleConten->setFont(TitleFont);
    m_TitleConten->setText(tr("自定义标题栏"));

    m_TitleIcon = new QLabel(this);                            // 标题栏左上角图标
    m_TitleIcon->setPixmap(QPixmap(":/icon/icon.png"));


    QHBoxLayout *hbox = new QHBoxLayout(this);           // 新建水平容器,把所有控件放在容器中
    hbox->addWidget(m_TitleIcon);
    hbox->addWidget(m_TitleConten);
    hbox->addWidget(m_Minimize);
    hbox->addWidget(m_Maximize);
    hbox->addWidget(m_Close);

    hbox->setSpacing(5);                      // 设置容器的属性,标题栏高度等
    hbox->setContentsMargins(5, 2, 5, 2);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    this->setFixedHeight(TITLE_HEIGHT);
    this->setStyleSheet("border-style:flat");
    setAttribute(Qt::WA_TranslucentBackground);

}

/*用于重新绘制标题栏,当外部调用了设置标题栏相关属性的函数时调用*/
void myTitleBar::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    QLinearGradient linearGradient(QPointF(0, 0), QPointF(0, this->height()));

    // 设置渐变的颜色,如果m_ColorL和m_ColorR相同时为纯色,而不是渐变色
    linearGradient.setColorAt(0, m_ColorL);  
    linearGradient.setColorAt(1, m_ColorR);

    linearGradient.setSpread(QGradient::ReflectSpread);
    painter.setBrush(linearGradient);
    QPen pen(m_Color);
    painter.setPen(pen);
    QPainterPath pathBack;                 // 先在QPainterPath画图,再用QPainter显示出来
    pathBack.setFillRule(Qt::WindingFill);
    pathBack.addRoundedRect(QRect(0, 0, this->width(), this->height()), 0, 0);

}

// 最小化
void myTitleBar::ShowSmall()
{
    parentWidget()->showMinimized();
}

//最大化/还原
void myTitleBar::ShowMaxRestore()
{
    if (m_MaxNormal) {
        parentWidget()->showNormal();
        m_MaxNormal = !m_MaxNormal;
        m_Maximize->setToolTip("最大化");
        m_Maximize->setIcon(*m_MaxPix);
    } else {
        parentWidget()->showMaximized();
        m_Maximize->setToolTip("向下还原");
        m_MaxNormal = !m_MaxNormal;
        m_Maximize->setIcon(*m_RestorePix);
    }
}

// 当鼠标点击了标题栏,记录下当时的位置
void myTitleBar::mousePressEvent(QMouseEvent *e)
{
    m_StartPos = e->globalPos();
    m_ClickPos = mapToParent(e->pos());
}

// 鼠标移动
void myTitleBar::mouseMoveEvent(QMouseEvent *e)
{
    if (m_MaxNormal)  // 如果处于最大化状态,则不能移动
        return;
    parentWidget()->move(e->globalPos() - m_ClickPos);
}

// 双击鼠标左键和放大按钮效果一致
void myTitleBar::mouseDoubleClickEvent(QMouseEvent *e)
{
    if(e->button() == Qt::LeftButton)
    {
        ShowMaxRestore();
    }
}



//设置标题栏的渐变色
void myTitleBar::SetTitleBackground(QColor ColorL,QColor ColorR )
{
    m_ColorL = ColorL;
    m_ColorR = ColorR;

    update();     // 通知更改,系统自动条用PainterEvent()函数
}


// 设置标题栏显示的文字
void myTitleBar::SetTitleContent(QString content)
{
    m_TitleConten->setText(content);
}

// 设置标题栏左上角的图标
void myTitleBar::SetTitleIcon(QString iconPath)
{
    QPixmap map(iconPath);
    m_TitleIcon->setPixmap(map);

}

自定义标题栏的代码如上所示,但是上面的代码不能直接运行哟。这里只是给出了自定义标题栏的代码,具体验证的也挺简单的,新建一个类,把默认的标题栏隐藏,直接new出来我们自定义的标题栏
myTitleBar *title = new myTitleBar(this),然后通过move函数把,title放在窗口的最上面就可以了。这样自定义标题栏就完成了。