前言
使用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放在窗口的最上面就可以了。这样自定义标题栏就完成了。