Qt自定義標題欄詳細介紹(可拖動、放大縮小、關閉、標題欄具有漸變色)
阿新 • • 發佈:2019-01-22
前言
使用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放在視窗的最上面就可以了。這樣自定義標題欄就完成了。