Qt自定义标题栏
第一次寫博客。剛發(fā)布出來,發(fā)現(xiàn)格式不滿意就刪了,結(jié)果回來看,保存的也沒了,真?zhèn)?。還好有個回收箱,又復(fù)制了一遍。
話不多上,先上效果圖:
圖片效果是加上了樣式與透明效果。這里只講標(biāo)題欄的創(chuàng)建方法,透明效果與樣式我會在下一次介紹。為了讓大家能夠看清楚效果,上圖是我以桌面作為背景。
相信大家可能已經(jīng)查了很多資料,或者說剛看到我的這篇博客,不過都沒關(guān)系,因為,看完我這篇,你們這個問題就可以解決了。大家每次本來把樣式整的漂漂亮亮的,卻因為系統(tǒng)的自帶標(biāo)題欄,導(dǎo)致整個程序頁面的美感多了一點瑕疵。
自定義標(biāo)題欄不僅可以讓我們自由在標(biāo)題欄上添加?xùn)|西,更方便設(shè)計主題,如下面的QQ音樂頁面。下面介紹自定義標(biāo)題欄的三種方法,第一二種方法只介紹思路,詳細會介紹第三種方法,也是我目前認為比較好的方法:
第一種:
1.去掉系統(tǒng)自帶的標(biāo)題欄。
2.在界面文件中,用控件在界面頂部布局一個標(biāo)題欄。
這種方法優(yōu)點是方便樣式的設(shè)置,能更好的設(shè)置主題,而且設(shè)計起來也更簡單。缺點是每次都要在新創(chuàng)建的工程中重新布局,還要設(shè)置變量,非常的麻煩與浪費多余寶貴的時間,如果是MainWindow窗口,這個方法就不能用了。這個方法就不多去介紹了。
第二種方法:
1、創(chuàng)建一個新的QWidget類,將這個QWidget設(shè)計成標(biāo)題欄,然后再將這個QWidget類加到UI界面文件的頂部,這樣每次新建工程,只需要將標(biāo)題欄的.c和.h文件加到工程中,復(fù)制使用代碼,就可以加入自定義的標(biāo)題欄了,非常的方便。但是這個方法缺點是,UI界面的定義必須留一段空的控件放標(biāo)題欄,與第一種方法有相同的限制,而且遇到MainWindow,會覆蓋在菜單欄上,使用代碼調(diào)整位置也效果不大。這種的負面效果圖當(dāng)時沒保存,就不重新花時間弄一遍了。
相信大家查找資料,很多都是第一種第二種方法,而且絕大部分資料都沒有考慮MainWindow工程與自己自定的標(biāo)題欄能不能適用。博主當(dāng)時查找資料也沒有看到滿意的資料,我希望能自定義一個標(biāo)題欄,然后不影響工程的界面文件設(shè)計,以后新建工程的時候,能直接把標(biāo)題欄文件加入工程就可以用了。后來查找資料過程中受到一句話啟發(fā),終于完美的解決了這個問題。下面介紹第三種方法。
第三種方法:
第三種方法與第二種方法非常類似。下面介紹思路:
先定義一個新的QWidget類 ,設(shè)為TitleBar,將它設(shè)計成標(biāo)題欄。再定義一個新的QWidget類,設(shè)為WidgetPar,這個類作為容器,后面說到。然后在創(chuàng)建的工程中的構(gòu)造函數(shù)中,將新建的標(biāo)題欄類和工程的界面文件做一個整體布局,然后把他們添加到WidgetPar這個類容器中,這樣就實現(xiàn)了自定義標(biāo)題欄。這個方法使得添加標(biāo)題欄非常方便,不影響原有的UI界面文件設(shè)計,而且對界面文件是哪個基類沒有任何影響。效果圖就是最開始看到的那個了。
設(shè)計標(biāo)題欄就不多介紹了,就是重寫事件,將標(biāo)題欄的那些功能在自定義的標(biāo)題欄上實現(xiàn)。
下面介紹代碼:
titlebar.c和titlebar.h就是標(biāo)題欄文件。
使用方法,在工程新建一個QWidget類,名字可以取上面一樣的,然后將下面的代碼復(fù)制上去。(類名相同可以全部替換)
titlebar.h
#ifndef TITLEBAR_H #define TITLEBAR_H#include <QWidget> #include <QLabel> #include <QPushButton>/* 定義一個新的QWidget類,將標(biāo)題欄和UI界面都放到這個類里面,定義這個類是為了方便改變主題 */ class WidgetPar : public QWidget {Q_OBJECT public:explicit WidgetPar(QWidget *parent = 0);signals:public slots://void paintEvent(QPaintEvent *event); };/* 自定義的標(biāo)題欄類 */ class TitleBar : public QWidget {Q_OBJECT public:explicit TitleBar(QWidget *parent = 0);signals:public slots://右上角三個按鈕共用一個槽函數(shù)void on_TiBar_Clicked();protected://重寫鼠標(biāo)事件virtual void mouseDoubleClickEvent(QMouseEvent *event);// 雙擊標(biāo)題欄進行界面的最大化/還原virtual void mousePressEvent(QMouseEvent *event);// 進行鼠界面的拖動virtual bool eventFilter(QObject *obj, QEvent *event);// 設(shè)置界面標(biāo)題與圖標(biāo)// 標(biāo)題欄跑馬燈效果時鐘;//QTimer m_titleRollTimer; private:void updateMaximize();// 最大化/還原private://自定義標(biāo)題欄控件QLabel *TiBar_pIconLabel; //左上角圖標(biāo)labelQLabel *TiBar_pTitleLabel; //中間標(biāo)題欄labelQPushButton *TiBar_pMinimizeBtn; //右上角縮小到底部任務(wù)欄按鈕,最小化QPushButton *TiBar_pMaximizeBtn; //右上角放大縮小按鈕QPushButton *TiBar_pCloseBtn; //右上角關(guān)閉按鈕 public:};#endif // TITLEBAR_Htitlebar.c
#include "titlebar.h" #include <QHBoxLayout> #include <QEvent> #include <QMouseEvent> #include <QApplication>#include <qt_windows.h> #include <QPainter>#include <QDebug> TitleBar::TitleBar(QWidget *parent) :QWidget(parent) {TiBar_pIconLabel = new QLabel;TiBar_pTitleLabel = new QLabel;TiBar_pMinimizeBtn = new QPushButton;TiBar_pMaximizeBtn = new QPushButton;TiBar_pCloseBtn = new QPushButton;TiBar_pIconLabel->setFixedSize(32, 32); //設(shè)置圖標(biāo)固定大小TiBar_pIconLabel->setScaledContents(true); //設(shè)置圖片顯示合適大小TiBar_pTitleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);//此屬性保存窗口小部件的默認布局行為。TiBar_pMinimizeBtn->setFixedSize(32, 32);//設(shè)置三個按鈕的固定大小TiBar_pMaximizeBtn->setFixedSize(32, 32);TiBar_pCloseBtn->setFixedSize(32, 32);TiBar_pTitleLabel->setFixedHeight(32);TiBar_pMinimizeBtn->setIcon(QIcon(":/image/image/small.ico"));TiBar_pMinimizeBtn->setIconSize(TiBar_pMinimizeBtn->size());TiBar_pMaximizeBtn->setIcon(QIcon(":/image/image/max.ico"));TiBar_pMaximizeBtn->setIconSize(TiBar_pMinimizeBtn->size());TiBar_pCloseBtn->setIcon(QIcon(":/image/image/close.ico"));TiBar_pCloseBtn->setIconSize(TiBar_pMinimizeBtn->size());QPixmap icon(":/image/image/lk.ico");TiBar_pIconLabel->setPixmap(icon);//TiBar_pIconLabel->resize(icon.width(),icon.height());TiBar_pTitleLabel->setObjectName("whiteLabel"); //此屬性保存此對象的名稱。TiBar_pMinimizeBtn->setObjectName("minimizeButton");TiBar_pMaximizeBtn->setObjectName("maximizeButton");TiBar_pCloseBtn->setObjectName("closeButton");TiBar_pMinimizeBtn->setToolTip("最小化"); //鼠標(biāo)停留在上面的提示TiBar_pMaximizeBtn->setToolTip("放大/縮小");TiBar_pCloseBtn->setToolTip("關(guān)閉");QHBoxLayout *pLayout = new QHBoxLayout(this);pLayout->addWidget(TiBar_pIconLabel);//pLayout->addSpacing(5);pLayout->addWidget(TiBar_pTitleLabel);pLayout->addWidget(TiBar_pMinimizeBtn);pLayout->addWidget(TiBar_pMaximizeBtn);pLayout->addWidget(TiBar_pCloseBtn);pLayout->setSpacing(0);//設(shè)置控件之間的間距pLayout->setContentsMargins(0, 0, 0, 0);//設(shè)置左上右下的邊距this->setLayout(pLayout);connect(TiBar_pMinimizeBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));connect(TiBar_pMaximizeBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked()));connect(TiBar_pCloseBtn,SIGNAL(clicked()),this,SLOT(on_TiBar_Clicked())); } /* 標(biāo)題欄右上角三個按鈕的槽函數(shù)*/ void TitleBar::on_TiBar_Clicked() {QPushButton *pBtn = qobject_cast<QPushButton *>(sender());//如果在由信號激活的槽中調(diào)用,則返回指向發(fā)送信號的對象的指針; 否則它返回0./* 返回此窗口小部件的窗口,即具有(或可能具有)窗口系統(tǒng)框架的下一個祖先窗口小部件。 如果窗口小部件是窗口,則返回窗口小部件本身。*/QWidget *pWindow = this->window();if (pWindow->isWindow())//如果窗口小部件是獨立窗口,則返回true,否則返回false。{if (pBtn == TiBar_pMinimizeBtn){pWindow->showMinimized();//最小化窗口小部件,作為圖標(biāo)。調(diào)用此函數(shù)僅影響窗口。}else if (pBtn == TiBar_pMaximizeBtn){pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();//放大縮小}else if (pBtn == TiBar_pCloseBtn){pWindow->close();//關(guān)閉窗口}} }void TitleBar::mouseDoubleClickEvent(QMouseEvent *event) {Q_UNUSED(event);emit TiBar_pMaximizeBtn->clicked(); }void TitleBar::mousePressEvent(QMouseEvent *event) {if (ReleaseCapture()){QWidget *pWindow = this->window();if (pWindow->isWindow()){SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);}}event->ignore(); }bool TitleBar::eventFilter(QObject *obj, QEvent *event) {switch (event->type()){case QEvent::WindowTitleChange:{QWidget *pWidget = qobject_cast<QWidget *>(obj);if (pWidget){TiBar_pTitleLabel->setText(pWidget->windowTitle());return true;}}case QEvent::WindowIconChange:{QWidget *pWidget = qobject_cast<QWidget *>(obj);if (pWidget){QIcon icon = pWidget->windowIcon();TiBar_pIconLabel->setPixmap(icon.pixmap(TiBar_pIconLabel->size()));return true;}}case QEvent::WindowStateChange:case QEvent::Resize://updateMaximize();return true;default:return false;}return QWidget::eventFilter(obj, event); } //窗口大小發(fā)生改變 void TitleBar::updateMaximize() {QWidget *pWindow = this->window();if (pWindow->isTopLevel()){bool bMaximize = pWindow->isMaximized();if (bMaximize){TiBar_pMaximizeBtn->setToolTip(tr("Restore"));TiBar_pMaximizeBtn->setProperty("maximizeProperty", "restore");}else{TiBar_pMaximizeBtn->setProperty("maximizeProperty", "maximize");TiBar_pMaximizeBtn->setToolTip(tr("Maximize"));}TiBar_pMaximizeBtn->setStyle(QApplication::style());} }WidgetPar::WidgetPar(QWidget *parent) :QWidget(parent) {}mainwindow.cpp
#include <QGridLayout> #include "titlebar.h"ui->setupUi(this);WidgetPar *selMainWidget = new WidgetPar; //創(chuàng)建一個QWidget容器selMainWidget->setWindowFlags(Qt::FramelessWindowHint);//將這個QWidget的邊框去掉this->setParent(selMainWidget);//重新設(shè)置這個UI界面的父對象為QWidgetTitleBar *pTitleBar = new TitleBar(selMainWidget); //定義一個標(biāo)題欄類//設(shè)置控件樣式//selMainWidget->setStyleSheet("background-color:#AFFFFF00");this->installEventFilter(pTitleBar);//安裝事件過濾器QGridLayout *pLayout = new QGridLayout();//創(chuàng)建一個整體布局器pLayout->addWidget(pTitleBar); //添加標(biāo)題欄pLayout->addWidget(this); //添加UI界面pLayout->setSpacing(0); //布局之間的距離pLayout->setContentsMargins(0, 0, 0,0); //布局器的四周邊距selMainWidget->setLayout(pLayout); //將這個布局器設(shè)置在QWidget上selMainWidget->setAttribute(Qt::WA_TranslucentBackground, true);selMainWidget->setSizePolicy(this->sizePolicy());selMainWidget->setMaximumSize(this->maximumSize());selMainWidget->setMaximumSize(this->maximumSize());this->setWindowTitle("自定義標(biāo)題欄成功 -----By DS_LK");selMainWidget->show();//顯示QWidge 最后添加大家按照這個方法基本沒問題了。QT版本是用的qt5.3的。
參考資料: 一去丶二三里
總結(jié)
- 上一篇: 基于深度指标的网络脆弱性攻击代价定量评估
- 下一篇: android 人脸 sdk,Andro