1. 程式人生 > >關於自定義的Qt無邊框窗體

關於自定義的Qt無邊框窗體

       現在桌面軟體的設計風格已經偏向於扁平化了。那麼基於Qt開發的桌面應用也會常常被提出扁平化無邊框的需求。怎麼去掉應用程式旁邊土到渣的邊框呢?本文應該可以幫到你。

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = QBaseFramelessWidget
TEMPLATE = app


SOURCES += main.cpp\
        qbaseframelesswidget.cpp \
    settingframelesswidget.cpp

HEADERS  += qbaseframelesswidget.h \
    settingframelesswidget.h
 /// qbaseframelesswidget.h
#ifndef QBASEFRAMELESSWIDGET_H
#define QBASEFRAMELESSWIDGET_H

#include <QWidget>
#include <QPushButton>
#include <QMouseEvent>
#include <QStyle>
#include <QIcon>
#include <QString>
#include <QDebug>

class QBaseFramelessWidget : public QWidget
{
    Q_OBJECT

public:
    QBaseFramelessWidget(QWidget *parent = 0);
    ~QBaseFramelessWidget();

    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseMoveEvent(QMouseEvent *event);
public:
    /// 窗體移動事件的點
    QPoint windowPos;
    QPoint mousePos;
    QPoint dPos;
private slots:
    /// 最小化窗體
    void onMin( bool );
    /// 關閉窗體
    void onClose( bool );
private:
    /// true表示當前視窗狀態為normal,圖示應顯示為max
    bool minOrNormal;
public:
    /// 顯示最大或者normal的圖示按鈕
    QPushButton* m_minOrNormalPushBtn; 
    /// 關閉按鈕
    QPushButton* m_closePushBtn;
};

#endif // QBASEFRAMELESSWIDGET_H
/// qbaseframelesswidget.cpp
#include "qbaseframelesswidget.h"

QBaseFramelessWidget::QBaseFramelessWidget(QWidget *parent)
    : QWidget(parent)
{
    this->setWindowFlags(Qt::FramelessWindowHint |
                         Qt::WindowSystemMenuHint |
                         Qt::WindowMinMaxButtonsHint);


    minOrNormal = true; /// 初始化預設為normal狀態
    m_minOrNormalPushBtn = new QPushButton(this);
    m_closePushBtn = new QPushButton(this);
    m_minOrNormalPushBtn->raise();
    m_closePushBtn->raise();

# if 0    ///  這裡只是做顯示,具體大位置可以自定義設定
    m_closePushBtn->setGeometry(QRect(300,8,25,25));
    m_minOrNormalPushBtn->setGeometry(QRect(330,8,25,25));

    m_closePushBtn->setFlat(true);
    m_minOrNormalPushBtn->setFlat(true);
#endif

    QIcon icon;
    if( minOrNormal ){/// true means normal
        /// normal時顯示最小化圖示
        icon = style()->standardIcon( QStyle::SP_TitleBarMinButton );
        m_minOrNormalPushBtn->setIcon( icon );
        m_minOrNormalPushBtn->setToolTip(QObject::tr("Min"));
    }

    icon = style()->standardIcon( QStyle::SP_TitleBarCloseButton );
    m_closePushBtn->setIcon( icon );
    m_closePushBtn->setToolTip(QObject::tr("Quit"));

    connect( m_minOrNormalPushBtn, SIGNAL(clicked(bool)), this, SLOT( onMin(bool)) );
    connect( m_closePushBtn, SIGNAL(clicked(bool)), this, SLOT( onClose(bool)) );

}

QBaseFramelessWidget::~QBaseFramelessWidget()
{

}
void QBaseFramelessWidget::onMin(bool)
{
    if( windowState() != Qt::WindowMinimized ){
        setWindowState( Qt::WindowMinimized );
    }
    m_minOrNormalPushBtn->setToolTip(QObject::tr("Min"));
}

void QBaseFramelessWidget::onClose(bool)
{
    emit close();
}


void QBaseFramelessWidget::mousePressEvent(QMouseEvent *event)
{

    this->windowPos = this->pos();           // 獲得部件當前位置
    this->mousePos = event->globalPos();     // 獲得滑鼠位置
    this->dPos = mousePos - windowPos;       // 移動後部件所在的位置

}

void QBaseFramelessWidget::mouseMoveEvent(QMouseEvent *event)
{
    this->move(event->globalPos() - this->dPos);
}

想要寫出既要無窗體可移動,又要包含自己特性的窗體的話,只需要繼承上面的類,寫一個子類就可以了。

#ifndef SETTINGFRAMELESSWIDGET_H
#define SETTINGFRAMELESSWIDGET_H

#include <QObject>
#include <QWidget>
#include "qbaseframelesswidget.h"

class settingFramelessWidget : public QBaseFramelessWidget
{
public:
    settingFramelessWidget();
};

#endif // SETTINGFRAMELESSWIDGET_H
#include "settingframelesswidget.h"

settingFramelessWidget::settingFramelessWidget()
{

}

 

在main.cpp函式中執行,測試效果:

#include "qbaseframelesswidget.h"
#include <QApplication>
#include "settingframelesswidget.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    QBaseFramelessWidget w;
//    w.show();

    settingFramelessWidget sfw;
    sfw.show();

    return a.exec();
}

生成如下所示的介面: