1 頭文件windows
#ifndef TITLEBAR_H #define TITLEBAR_H #include <QLabel> #include <QPushButton> #include "ui_TitleBar.h" class TitleBar : public QWidget { Q_OBJECT public: explicit TitleBar(QWidget *parent = nullptr); ~TitleBar(); void setMiniBtnIcon(const QIcon& icon); void setMaxiBtnIcon(const QIcon& icon); void setCloseBtnIcon(const QIcon& icon); protected: //鼠標雙擊事件 virtual void mouseDoubleClickEvent(QMouseEvent *event); //鼠標按下事件 virtual void mousePressEvent(QMouseEvent *event); //鼠標釋放事件 virtual void mouseReleaseEvent(QMouseEvent *event); //鼠標移動事件 virtual void mouseMoveEvent(QMouseEvent *event); //設置界面標題與圖標 virtual bool eventFilter(QObject *obj, QEvent *event); private slots: //進行最小化、最大化/還原、關閉操做 void onClicked(); private: //最大化/還原 void updateMaximize(); private: Ui::TitleBar ui; QPoint pos; //鼠標當前點擊座標 bool mouse_press; //鼠標按下 }; #endif // TitleBar_H
2 cpp文件less
#include <QLabel> #include <QPushButton> #include <QHBoxLayout> #include <QEvent> #include <QMouseEvent> #include <QApplication> #include "TitleBar.h" //調用WIN API #ifdef Q_OS_WIN #include <qt_windows.h> #endif TitleBar::TitleBar(QWidget *parent) : QWidget(parent) { ui.setupUi(this); mouse_press = false; //setFixedHeight(30); // 設置窗口背景透明; //setAttribute(Qt::WA_TranslucentBackground); //給按鈕設置靜態tooltip,當鼠標移上去時顯示tooltip ui.btnMinimize->setToolTip(tr("Minimize")); ui.btnMaximize->setToolTip(tr("Maximize")); ui.btnClose->setToolTip(tr("Close")); QPalette pal(palette()); pal.setColor(QPalette::Background, QColor(150, 150, 150)); setAutoFillBackground(true); setPalette(pal); connect(ui.btnMinimize, SIGNAL(clicked(bool)), this, SLOT(onClicked())); connect(ui.btnMaximize, SIGNAL(clicked(bool)), this, SLOT(onClicked())); connect(ui.btnClose, SIGNAL(clicked(bool)), this, SLOT(onClicked())); //隱藏更換皮膚按鈕 ui.btnSkin->setVisible(false); setAttribute(Qt::WA_StyledBackground); } TitleBar::~TitleBar() { } //雙擊標題欄進行界面的最大化/還原 void TitleBar::mouseDoubleClickEvent(QMouseEvent *event) { Q_UNUSED(event); emit ui.btnMaximize->clicked(); } void TitleBar::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { mouse_press = true; pos = event->globalPos(); } event->ignore(); } void TitleBar::mouseMoveEvent(QMouseEvent *event) { //若鼠標左鍵被按下 if (mouse_press) { QPoint move_pos = event->globalPos()-pos; //鼠標如今位置-原來位置 //移動主窗體 window()->move(window()->pos() + move_pos);//窗口位置+鼠標移動距離 pos = event->globalPos(); //更新位置 } event->ignore(); } void TitleBar::mouseReleaseEvent(QMouseEvent *event) { //設置鼠標爲未被按下 mouse_press = false; event->ignore(); } //使用事件過濾器監聽標題欄所在的窗體,因此當窗體標題、圖標等信息發生改變時,標題欄也應該隨之改變 bool TitleBar::eventFilter(QObject *obj, QEvent *event) { switch (event->type()) { //判斷髮生事件的類型 case QEvent::WindowTitleChange: { //窗口標題改變事件 QWidget *pWidget = qobject_cast<QWidget *> (obj); //得到發生事件的窗口對象 if (pWidget) { //窗體標題改變,則標題欄標題也隨之改變 ui.labelTitle->setText(pWidget->windowTitle()); return true; } } break; case QEvent::WindowIconChange: { //窗口圖標改變事件 QWidget *pWidget = qobject_cast<QWidget *>(obj); if (pWidget) { //窗體圖標改變,則標題欄圖標也隨之改變 QIcon icon = pWidget->windowIcon(); // ui.labelIcon->setPixmap(icon.pixmap(ui.labelIcon->size())); return true; } } break; case QEvent::Resize: updateMaximize(); //最大化/還原 return true; default: return QWidget::eventFilter(obj, event); } return QWidget::eventFilter(obj, event); } //進行最小化、最大化/還原、關閉操做 void TitleBar::onClicked() { QPushButton *pButton = qobject_cast<QPushButton *>(sender()); QWidget *pWindow = this->window(); //得到標題欄所在的窗口 if (pWindow->isTopLevel()) { if (pButton == ui.btnMinimize) { pWindow->showMinimized(); //窗口最小化顯示 } else if (pButton == ui.btnMaximize) { pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized(); //窗口最大化/還原顯示 } else if (pButton == ui.btnClose) { pWindow->close(); //窗口關閉 } } } //最大化/還原 void TitleBar::updateMaximize() { QWidget *pWindow = this->window(); //得到標題欄所在的窗口 if (pWindow->isTopLevel()) { bool bMaximize = pWindow->isMaximized(); //判斷窗口是否是最大化狀態,是則返回true,不然返回false if (bMaximize) { //目前窗口是最大化狀態,則最大化/還原的toolTip設置爲"Restore" ui.btnMaximize->setToolTip(tr("Restore")); //設置按鈕的屬性名爲"maximizeProperty" ui.btnMaximize->setProperty("maximizeProperty", "restore"); } else { //目前窗口是還原狀態,則最大化/還原的toolTip設置爲"Maximize" ui.btnMaximize->setToolTip(tr("Maximize")); //設置按鈕的屬性名爲"maximizeProperty" ui.btnMaximize->setProperty("maximizeProperty", "maximize"); } ui.btnMaximize->setStyle(QApplication::style()); } } void TitleBar::setMiniBtnIcon(const QIcon& icon) { ui.btnMinimize->setIcon(icon.pixmap(ui.btnMinimize->size())); } void TitleBar::setMaxiBtnIcon(const QIcon& icon) { ui.btnMaximize->setIcon(icon.pixmap(ui.btnMaximize->size())); } void TitleBar::setCloseBtnIcon(const QIcon& icon) { ui.btnClose->setIcon(icon.pixmap(ui.btnClose->size())); }
3 使用說明函數
自定義標題欄使用說明(包含TitleBar.h,TitleBar.cpp,TitleBar.ui三個文件): 1主窗體類中添加頭文件: //調用WIN API須要用到的頭文件 [實現縮放] #ifdef Q_OS_WIN #include <qt_windows.h> #include <Windowsx.h> #endif 2主窗體類中 添加成員變量: int m_nBorderWidth;//表示鼠標位於邊框縮放範圍的寬度 添加成員函數: //nativeEvent主要用於進程間通訊-消息傳遞,使用這種方式後來實現窗體的縮放 bool xxx::nativeEvent(const QByteArray &eventType, void *message, long *result) { Q_UNUSED(eventType) MSG *param = static_cast<MSG *>(message); switch (param->message) { case WM_NCHITTEST: { int nX = GET_X_LPARAM(param->lParam) - this->geometry().x(); int nY = GET_Y_LPARAM(param->lParam) - this->geometry().y(); // 若是鼠標位於子控件上,則不進行處理 if (childAt(nX, nY) != nullptr) return QWidget::nativeEvent(eventType, message, result); *result = HTCAPTION; // 鼠標區域位於窗體邊框,進行縮放 if ((nX > 0) && (nX < m_nBorderWidth)) *result = HTLEFT; if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())) *result = HTRIGHT; if ((nY > 0) && (nY < m_nBorderWidth)) *result = HTTOP; if ((nY > this->height() - m_nBorderWidth) && (nY < this->height())) *result = HTBOTTOM; if ((nX > 0) && (nX < m_nBorderWidth) && (nY > 0) && (nY < m_nBorderWidth)) *result = HTTOPLEFT; if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()) && (nY > 0) && (nY < m_nBorderWidth)) *result = HTTOPRIGHT; if ((nX > 0) && (nX < m_nBorderWidth) && (nY > this->height() - m_nBorderWidth) && (nY < this->height())) *result = HTBOTTOMLEFT; if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()) && (nY > this->height() - m_nBorderWidth) && (nY < this->height())) *result = HTBOTTOMRIGHT; return true; } } return QWidget::nativeEvent(eventType, message, result); } 3 在widget中應用自定義標題欄 (1)在須要添加自定義標題欄的widget的ui文件中,拖動一個widget加入到當前widget佈局的最上方,而後提高控件類爲TitleBar (2)主窗體類的構造函數中添加以下代碼: //Qt::FramelessWindowHint設置窗口標誌爲無邊框,而Qt::WindowStaysOnTopHint使窗口位於全部界面之上 setWindowFlags(Qt::FramelessWindowHint); //ui中提高控件 installEventFilter(ui.widget);//ui.widget 爲佈局中提高的自定義標題控件 //設置標題欄標題 圖標 按鈕圖標,可在ui文件中直接修改,也可在代碼中修改 setWindowTitle("Custom Window"); setWindowIcon(QIcon("")); ui.widget->setMiniBtnIcon(QIcon("")); ui.widget->setMaxiBtnIcon(QIcon("")); ui.widget->setCloseBtnIcon(QIcon("")); m_nBorderWidth= 5; 4 在mainwindow中應用自定義標題欄 (1)新建一個widget,拖動一個子widget到當前widget佈局的最上放,提高控件爲TitleBar (2) 在當前widget的類中添加頭文件,成員變量和成員函數,同上 (3)在當前widget的構造函數中添加以下代碼 //Qt::FramelessWindowHint設置窗口標誌爲無邊框,而Qt::WindowStaysOnTopHint使窗口位於全部界面之上 setWindowFlags(Qt::FramelessWindowHint); //ui中提高控件 installEventFilter(ui.widget);//ui.widget 爲佈局中提高的自定義標題控件 //設置標題欄標題 圖標 按鈕圖標,可在ui文件中直接修改,也可在代碼中修改 /* setWindowTitle("Custom Window"); setWindowIcon(QIcon("")); ui.widget->setMiniBtnIcon(QIcon("")); ui.widget->setMaxiBtnIcon(QIcon("")); ui.widget->setCloseBtnIcon(QIcon("")); */ m_nBorderWidth= 5; //MainWindow爲須要添加自定義標題欄的主界面類 MainWindow *maindow = new MainWindow(this); maindow->setWindowFlags(Qt::FramelessWindowHint); /* QVBoxLayout *vlayout = new QVBoxLayout; vlayout->addWidget(ui.titlebar_widget_); QString path = QStringLiteral(":/png/最小化.png"); QIcon minicon(path); ui.titlebar_widget_->setMiniBtnIcon(minicon); path = QStringLiteral(":/png/窗口.png"); QIcon maxicon(path); ui.titlebar_widget_->setMaxiBtnIcon(maxicon); path = QStringLiteral(":/png/關 閉.png"); QIcon closeicon(path); ui.titlebar_widget_->setCloseBtnIcon(closeicon); QString filestyle = QStringLiteral("background-image: url(:/png/標題欄-背景.png);"); ui.titlebar_widget_->setStyleSheet(filestyle); */ QVBoxLayout *vlayout = new QVBoxLayout; vlayout->addWidget(ui.titlebar_widget_); vlayout->addWidget(maindow); //設置佈局距離上下左右的距離,根據須要設置,也可在ui中修改 vlayout->setContentsMargins(2,1,2,1); setLayout(vlayout); (4)在顯示主界面的時候,在main函數中將MainWindow類換爲新加的widget,便可顯示自定義標題欄
4 ui文件見上傳文件佈局