Qt高級(jí)——Qt自定義標(biāo)題欄

Qt高級(jí)——Qt自定義標(biāo)題欄

一、Qt自定義標(biāo)題欄簡介

QWidget及其子類窗體組件的標(biāo)題欄受操作系統(tǒng)的控制,即標(biāo)題欄的界面風(fēng)格與操作系統(tǒng)的主題風(fēng)格相同,工程實(shí)踐中需要開發(fā)者自行定義,達(dá)到美化應(yīng)用程序界面的目的。

創(chuàng)新互聯(lián)專注于深州企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,成都商城網(wǎng)站開發(fā)。深州網(wǎng)站建設(shè)公司,為深州等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站設(shè)計(jì),專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

二、Qt自定義標(biāo)題欄實(shí)現(xiàn)

1、自定義標(biāo)題欄的功能

自定義標(biāo)題欄需要完成功能如下:
(1)自定義標(biāo)題欄需要包含最小化按鈕、最大化按鈕、關(guān)閉按鈕、標(biāo)題標(biāo)簽、圖標(biāo)標(biāo)簽等圖形元素。
(2)標(biāo)題欄的拖拽。
(3)鼠標(biāo)雙擊標(biāo)題欄實(shí)現(xiàn)窗體的最大化、最小化。

2、自定義標(biāo)題欄的界面布局

自定義標(biāo)題欄的界面布局如下:
Qt高級(jí)——Qt自定義標(biāo)題欄

3、標(biāo)題欄拖拽功能的實(shí)現(xiàn)

窗體的拖拽平移過程如下圖:
Qt高級(jí)——Qt自定義標(biāo)題欄
當(dāng)鼠標(biāo)在窗體的標(biāo)題欄按下并移動(dòng)時(shí),窗體會(huì)按照鼠標(biāo)移動(dòng)的軌跡進(jìn)行平移。因此,窗體每次移動(dòng)都是在當(dāng)前位置按照鼠標(biāo)移動(dòng)的矢量進(jìn)行移動(dòng)。標(biāo)題欄拖拽功能的實(shí)現(xiàn)需要實(shí)現(xiàn)mousePressEvent、mouseMoveEvent、mouseReleaseEvent三個(gè)事件處理函數(shù)。
MouseEvent中的globalPos()函數(shù)返回的是相對(duì)屏幕的位置坐標(biāo),而pos()則是返回鼠標(biāo)在當(dāng)前控件(即捕獲該鼠標(biāo)事件的控件)中的位置。
QWidget窗體的geometry().topLeft()則返回的是當(dāng)前窗體的左上角在屏幕中的位置。

startPos = event->globalPos();// 鼠標(biāo)的全局初始位置,按下時(shí)記住?
curWindowPos = geometry().topleft();// 窗體的全局位置,移動(dòng)時(shí)?
endPos = event->globalPos();// 鼠標(biāo)按下發(fā)生移動(dòng)之后的位置,移動(dòng)時(shí)?
move(curWindowPos+(startPos-endPos));// 根據(jù)矢量移動(dòng)方向是初始位置減去末位置,移動(dòng)時(shí)?
startPos = endPos;// 將初始位置記為上次末位置,然后執(zhí)行直到釋放拖拽,移動(dòng)時(shí)

實(shí)現(xiàn)代碼如下:

void TitleBar::mousePressEvent(QMouseEvent *event)
{
    // 鼠標(biāo)左鍵按下事件
    if (event->button() == Qt::LeftButton)
    {
        // 記錄鼠標(biāo)左鍵狀態(tài)
        m_leftButtonPressed = true;
        //記錄鼠標(biāo)在屏幕中的位置
        m_start = event->globalPos();
    }

}

void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
    // 持續(xù)按住才做對(duì)應(yīng)事件
    if(m_leftButtonPressed)
    {
        //將父窗體移動(dòng)到父窗體原來的位置加上鼠標(biāo)移動(dòng)的位置:event->globalPos()-m_start
        parentWidget()->move(parentWidget()->geometry().topLeft() +
                             event->globalPos() - m_start);
        //將鼠標(biāo)在屏幕中的位置替換為新的位置
        m_start = event->globalPos();
    }

}

void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
    // 鼠標(biāo)左鍵釋放
    if (event->button() == Qt::LeftButton)
    {
        // 記錄鼠標(biāo)狀態(tài)
        m_leftButtonPressed = false;
    }
}

4、標(biāo)題欄雙擊實(shí)現(xiàn)最大化、最小化

鼠標(biāo)雙擊事件處理函數(shù)mouseDoubleClickEvent實(shí)現(xiàn)如下:

void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    m_maximizeButton->click();
}

最大化、最小化、關(guān)閉按鈕的槽函數(shù)如下:

void TitleBar::onClicked()
{
    QPushButton *pButton = qobject_cast<QPushButton *>(sender());
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        if (pButton == m_minimizeButton)
        {
            pWindow->showMinimized();
        }
        else if (pButton == m_maximizeButton)
        {
            pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
        }
        else if (pButton == m_closeButton)
        {
            pWindow->close();
        }
    }
}

三、Qt自定義窗體基類示例

1、自定義窗體基類的功能

自定義窗體基類的功能如下:
(1)自定義標(biāo)題欄。
(2)增加內(nèi)容組件,內(nèi)容組件內(nèi)部的界面布局完全由具體的用戶決定。

2、自定義窗體基類的實(shí)現(xiàn)

TitleBar.h文件:

#ifndef TITLEBAR_H
#define TITLEBAR_H

#include <QWidget>
#include <QPushButton>
#include <QLabel>
#include <QHBoxLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QApplication>
#include <QPoint>
#include <QPixmap>
#include <QString>
/**
 * @brief 標(biāo)題欄界面組件
 * @author 
 */

class TitleBar : public QWidget
{
    Q_OBJECT
public:
    explicit TitleBar(QWidget *parent = NULL);
    /**
     * @brief 設(shè)置標(biāo)題欄標(biāo)題
     * @param title,參數(shù),設(shè)置的標(biāo)題
     */
    void setWindowTitle(const QString& title);
    /**
     * @brief 設(shè)置標(biāo)題欄的圖標(biāo)
     * @param iconPath,參數(shù),圖標(biāo)的路徑
     */
    void SetTitleBarIcon(const QString& iconPath);

protected:
    /**
     * @brief 鼠標(biāo)雙擊事件處理函數(shù)
     * @param event,參數(shù),事件
     * @note 雙擊標(biāo)題欄進(jìn)行界面的最大化/還原
     */
    virtual void mouseDoubleClickEvent(QMouseEvent *event);

    /**
     * @brief 鼠標(biāo)按下事件處理函數(shù)
     * @param event,參數(shù),事件
     * @note 按下鼠標(biāo)左鍵
     */
    virtual void mousePressEvent(QMouseEvent *event);
    /**
     * @brief 鼠標(biāo)移動(dòng)事件處理函數(shù)
     * @param event,參數(shù),事件
     * @note 移動(dòng)鼠標(biāo)
     */
    virtual void mouseMoveEvent(QMouseEvent *event);
    /**
     * @brief 鼠標(biāo)釋放事件處理函數(shù)
     * @param event,參數(shù),事件
     * @note 釋放鼠標(biāo)
     */
    virtual void mouseReleaseEvent(QMouseEvent *event);

    /**
     * @brief 事件過濾處理器
     * @param obj,參數(shù)
     * @param event,參數(shù),事件
     * @return 成功返回true,失敗返回false
     * @note 設(shè)置標(biāo)題、圖標(biāo)
     */
    virtual bool eventFilter(QObject *obj, QEvent *event);

    /**
     * @brief 最大化/還原
     */
    void updateMaximize();

protected slots:
    /**
     * @brief 最小化、最大化/還原、關(guān)閉按鈕點(diǎn)擊時(shí)響應(yīng)的槽函數(shù)
     */
    void onClicked();

private:
    QLabel* m_iconLabel;
    QLabel* m_titleLabel;
    QPushButton* m_minimizeButton;
    QPushButton* m_maximizeButton;
    QPushButton* m_closeButton;
    QPoint m_start;//起始點(diǎn)
    QPoint m_end;//結(jié)束點(diǎn)
    bool m_leftButtonPressed;//鼠標(biāo)左鍵按下標(biāo)記
};

#endif // TITLEBAR_H

TitleBar.cpp文件:

#include "TitleBar.h"

TitleBar::TitleBar(QWidget *parent) : QWidget(parent)
{
    setFixedHeight(30);
    setWindowFlags(Qt::FramelessWindowHint);
    m_iconLabel = new QLabel(this);
    m_iconLabel->setFixedSize(20, 20);
    m_iconLabel->setScaledContents(true);

    m_titleLabel = new QLabel(this);
    m_titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    m_minimizeButton = new QPushButton(this);
    m_minimizeButton->setFixedSize(27, 22);
    m_minimizeButton->setObjectName("minimizeButton");

    m_maximizeButton = new QPushButton(this);
    m_maximizeButton->setFixedSize(27, 22);
    m_maximizeButton->setObjectName("maximizeButton");

    m_closeButton = new QPushButton(this);
    m_closeButton->setFixedSize(27, 22);
    m_closeButton->setObjectName("closeButton");

    QHBoxLayout* layout = new QHBoxLayout;
    layout->addWidget(m_iconLabel);
    layout->addStretch(1);
    layout->addWidget(m_titleLabel);
    layout->addStretch(1);
    layout->addWidget(m_minimizeButton);
    layout->addWidget(m_maximizeButton);
    layout->addWidget(m_closeButton);
    setLayout(layout);

    setProperty("titleBar", true);
    setObjectName("titleBar");

    connect(m_minimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
    connect(m_maximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
    connect(m_closeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
}

void TitleBar::setWindowTitle(const QString &title)
{
    m_titleLabel->setAlignment(Qt::AlignCenter);
    m_titleLabel->setText(title);
}

void TitleBar::SetTitleBarIcon(const QString &iconPath)
{
    QPixmap map(iconPath);
    m_iconLabel->setPixmap(map);
}

void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
    m_maximizeButton->click();
}

void TitleBar::mousePressEvent(QMouseEvent *event)
{
    // 鼠標(biāo)左鍵按下事件
    if (event->button() == Qt::LeftButton)
    {
        // 記錄鼠標(biāo)左鍵狀態(tài)
        m_leftButtonPressed = true;
        //記錄鼠標(biāo)在屏幕中的位置
        m_start = event->globalPos();
    }

}

void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
    // 持續(xù)按住才做對(duì)應(yīng)事件
    if(m_leftButtonPressed)
    {
        //將父窗體移動(dòng)到父窗體原來的位置加上鼠標(biāo)移動(dòng)的位置:event->globalPos()-m_start
        parentWidget()->move(parentWidget()->geometry().topLeft() +
                             event->globalPos() - m_start);
        //將鼠標(biāo)在屏幕中的位置替換為新的位置
        m_start = event->globalPos();
    }

}

void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
    // 鼠標(biāo)左鍵釋放
    if (event->button() == Qt::LeftButton)
    {
        // 記錄鼠標(biāo)狀態(tài)
        m_leftButtonPressed = false;
    }
}

bool TitleBar::eventFilter(QObject *obj, QEvent *event)
{
    switch(event->type())
    {
    //設(shè)置標(biāo)題
    case QEvent::WindowTitleChange:
    {
        QWidget *pWidget = qobject_cast<QWidget *>(obj);
        if (pWidget)
        {
            m_titleLabel->setText(pWidget->windowTitle());
            return true;
        }
    }
    //設(shè)置圖標(biāo)
    case QEvent::WindowIconChange:
    {
        QWidget *pWidget = qobject_cast<QWidget *>(obj);
        if (pWidget)
        {
            QIcon icon = pWidget->windowIcon();
            m_iconLabel->setPixmap(icon.pixmap(m_iconLabel->size()));
            return true;
        }
    }
    // 窗口狀態(tài)變化、窗口大小變化
    case QEvent::WindowStateChange:
    case QEvent::Resize:
        updateMaximize();
        return true;
    }
    return QWidget::eventFilter(obj, event);
}

void TitleBar::updateMaximize()
{
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        bool bMaximize = pWindow->isMaximized();
        if (bMaximize)
        {
            m_maximizeButton->setToolTip(tr("Restore"));
            m_maximizeButton->setProperty("maximizeProperty", "restore");
        }
        else
        {
            m_maximizeButton->setProperty("maximizeProperty", "maximize");
            m_maximizeButton->setToolTip(tr("Maximize"));
        }

        m_maximizeButton->setStyle(QApplication::style());
    }
}

void TitleBar::onClicked()
{
    QPushButton *pButton = qobject_cast<QPushButton *>(sender());
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        if (pButton == m_minimizeButton)
        {
            pWindow->showMinimized();
        }
        else if (pButton == m_maximizeButton)
        {
            pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
        }
        else if (pButton == m_closeButton)
        {
            pWindow->close();
        }
    }
}

QWindowBase.h文件:

#ifndef QWINDOWBASE_H
#define QWINDOWBASE_H

#include <QFrame>
#include <QWidget>
#include <QVBoxLayout>
#include "TitleBar.h"

/**
 * @brief 界面組件基類
 * @note QWindowBase界面組件主要用作頂層窗口,對(duì)于非頂層窗口的界面組件使用QWidget。
 */
class QWindowBase : public QFrame
{
    Q_OBJECT
public:
    QWindowBase(QFrame* parent = NULL);
    /**
     * @brief 設(shè)置標(biāo)題
     * @param title,輸入?yún)?shù),標(biāo)題內(nèi)容
     */
    void setWindowTitle(const QString& title);
    /**
     * @brief 設(shè)置標(biāo)題欄的圖標(biāo)
     * @param iconPath,輸入?yún)?shù),圖標(biāo)資源路徑
     */
    void SetTitleBarIcon(const QString& iconPath);
    /**
     * @brief 獲取內(nèi)容組件對(duì)象指針
     * @return 返回QWidget*
     */
    QWidget* contentWidget();
    /**
     * @brief 設(shè)置標(biāo)題欄高度
     * @param h,輸入?yún)?shù),標(biāo)題欄高度
     */
    void setWindowTitleHeight(int h);

private:
    QWidget* m_contentWidget;//內(nèi)容組件
    TitleBar* m_titleBar;//標(biāo)題欄
    QVBoxLayout* m_layout;//布局管理器
};

#endif // QWINDOWBASE_H

QWindowBase.cpp文件:

#include "QWindowBase.h"

QWindowBase::QWindowBase(QFrame *parent): QFrame(parent)
{
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
    m_titleBar = new TitleBar(this);
    m_contentWidget = new QWidget(this);
    m_contentWidget->setObjectName("Contents");
    m_layout = new QVBoxLayout;
    m_layout->addWidget(m_titleBar);
    m_layout->addWidget(m_contentWidget);
    m_layout->setSpacing(0);
    m_layout->setContentsMargins(0, 0, 0, 0);

    setLayout(m_layout);
}

void QWindowBase::setWindowTitle(const QString &title)
{
    m_titleBar->setWindowTitle(title);
}

void QWindowBase::SetTitleBarIcon(const QString &iconPath)
{
    m_titleBar->SetTitleBarIcon(iconPath);
}

QWidget *QWindowBase::contentWidget()
{
    return m_contentWidget;
}

void QWindowBase::setWindowTitleHeight(int h)
{
    m_titleBar->setFixedHeight(h);
}

CommonHelper.h文件:

#ifndef COMMONHELPER_H
#define COMMONHELPER_H

#include <QString>
#include <QFile>
#include <QApplication>
#include <QDebug>
#include <QColor>
#include <QPalette>

/**
 * @brief 通用功能輔助類
 */
class CommonHelper
{
public:
    /**
     * @brief 為應(yīng)用程序設(shè)置QSS樣式表
     * @param filepath,輸入?yún)?shù),QSS文件路徑
     */
    static void setStyleSheet(const QString& filepath)
    {
        //加載樣式文件
        QFile qss(filepath);
        if(qss.open(QFile::ReadOnly))
        {
            QString stylesheet = QLatin1String(qss.readAll());
            QString paletteColor = stylesheet.mid(20, 7);
            qApp->setPalette(QPalette(QColor(paletteColor)));
            qApp->setStyleSheet(stylesheet);
        }
    }
};

#endif // COMMONHELPER_H

main.cpp文件:

#include <QApplication>
#include "CommonHelper.h"
#include "QWindowBase.h"
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTreeView>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWindowBase w;
    w.setWindowTitle("WidgetBase");
    QPushButton* button1 = new QPushButton("OK");
    QHBoxLayout* hLayout1 = new QHBoxLayout;
    hLayout1->addStretch(1);
    hLayout1->addWidget(button1);

    QVBoxLayout* layout = new QVBoxLayout;
    QTreeView* treeView = new QTreeView;
    layout->addWidget(treeView);
    layout->addLayout(hLayout1);
    layout->addStretch(1);
    w.contentWidget()->setLayout(layout);
    w.setWindowTitleHeight(40);
    w.show();
    CommonHelper::setStyleSheet("://qss/lightblue.qss");
    return a.exec();
}

工程文件:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = TitleBarDemo
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp \
    TitleBar.cpp \
    QWindowBase.cpp

HEADERS += \
    TitleBar.h \
    CommonHelper.h \
    QWindowBase.h

RESOURCES += \
    TitileBarDemo.qrc

工程目錄結(jié)構(gòu):
Qt高級(jí)——Qt自定義標(biāo)題欄

3、自定義窗體基類結(jié)果展示

運(yùn)行結(jié)果:
Qt高級(jí)——Qt自定義標(biāo)題欄

源碼:http://down.51cto.com/data/2457159

文章名稱:Qt高級(jí)——Qt自定義標(biāo)題欄
本文地址:http://muchs.cn/article4/geedie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司、網(wǎng)站設(shè)計(jì)公司定制網(wǎng)站、響應(yīng)式網(wǎng)站、、營銷型網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站