QT 自定义标题栏

自定义标题栏

要想做出好看的界面,qt自带的标题栏必须抛弃掉。

如何去掉qt窗口的标题栏

只需添加this->setWindowFlags(Qt::FramelessWindowHint)

以下是去掉标题栏的例子:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::FramelessWindowHint);//去掉窗口标题栏
}

MainWindow::~MainWindow()
{
    delete ui;
}

修改centralWidget布局

Qt的布局有4种

QT 自定义标题栏_第1张图片

四种布局方法:

  1. 水平布局类QHBoxLayout

  2. 垂直布局类QVBoxLayout

  3. 网格布局类QGridLayout

  4. 表单布局类QFormLayout

centralWidget默认布局是不可修改的

QT 自定义标题栏_第2张图片

要在centralWidget,需要对ui文件进行修改,但是在qt编辑模式里面提示mainwindow.ui这个文件只能在design模式下修改。

QT 自定义标题栏_第3张图片

要对qt的ui文件进行自定义修改,我们可以使用vim、sublime等文本编辑器直接打开ui文件

在对应的位置上添加布局(4选1):

class="QVBoxLayout" name="verticalLayout"/>
class="QHBoxLayout" name="horizontalLayout"/>
class="QGridLayout" name="gridLayout"/>
class="QFormLayout" name="formLayout"/>

修改前:

<ui version="4.0">
 <class>MainWindowclass>
 <widget class="QMainWindow" name="MainWindow" >
  <property name="geometry" >
   <rect>
    <x>0x>
    <y>0y>
    <width>400width>
    <height>300height>
   rect>
  property>
  <property name="windowTitle" >
   <string>MainWindowstring>
  property>
  <widget class="QMenuBar" name="menuBar" />
  <widget class="QToolBar" name="mainToolBar" />
  <widget class="QWidget" name="centralWidget" />
  <widget class="QStatusBar" name="statusBar" />
 widget>
 <layoutDefault spacing="6" margin="11" />
 <pixmapfunction>pixmapfunction>
 <resources/>
 <connections/>
ui>

修改后(例子:centralWidget添加垂直布局):

<ui version="4.0">
 <class>MainWindowclass>
 <widget class="QMainWindow" name="MainWindow" >
  <property name="geometry" >
   <rect>
    <x>0x>
    <y>0y>
    <width>400width>
    <height>300height>
   rect>
  property>
  <property name="windowTitle" >
   <string>MainWindowstring>
  property>
  <widget class="QMenuBar" name="menuBar" />
  <widget class="QToolBar" name="mainToolBar" />
  <widget class="QWidget" name="centralWidget" >
    <layout class="QVBoxLayout" name="verticalLayout"/>
  widget>
  <widget class="QStatusBar" name="statusBar" />
 widget>
 <layoutDefault spacing="6" margin="11" />
 <pixmapfunction>pixmapfunction>
 <resources/>
 <connections/>
ui>

文件保存后,回到qt,提示文件已改变,选择Yes to All

QT 自定义标题栏_第4张图片

可以看到centralWidget以及添加了垂直布局

QT 自定义标题栏_第5张图片

自定义

头文件 userdefineframe.h

#ifndef USERDEFINEFRAME_H
#define USERDEFINEFRAME_H

#include 

class QToolButton;
class QToolButton;
class UserDefineFrame : public QFrame
{
    Q_OBJECT
public:
    explicit UserDefineFrame(QWidget *contentWidget, const QString &title);

public slots:
    void slotShowSmall();
    void slotShowMaxRestore();

protected:
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    bool nativeEvent(const QByteArray & eventType, void * message, long * result);
    void paintEvent(QPaintEvent *);

private:
    bool isMax_;
    bool isPress_;
    QPoint startPos_;
    QPoint clickPos_;
    QWidget *contentWidget_;
    QPixmap maxPixmap_;
    QPixmap restorePixmap_;
    QToolButton *maxButton_;
};


#endif // USERDEFINEFRAME_H

cpp文件 userdefineframe.cpp

#include "userdefineframe.h"

#include <QtWidgets>

static const int TITLE_HEIGHT = 30;
static const int FRAME_BORDER = 2;
UserDefineFrame::UserDefineFrame(QWidget *contentWidget, const QString &title)
    : contentWidget_(contentWidget)
{
    // 隐藏标题栏
    this->setWindowFlags(Qt::FramelessWindowHint);
    // 设置窗体透明度
    //this->setWindowOpacity(0.7);
    // 窗体标题栏不透明,背景透明
    this->setAttribute(Qt::WA_TranslucentBackground);
    // 对鼠标进行监控
    this->setMouseTracking(true);

    isMax_ = false;
    isPress_ = false;

    // logo
    QLabel *logoLabel = new QLabel();
    QPixmap logoPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMenuButton);
    logoLabel->setPixmap(logoPixmap);
    logoLabel->setFixedSize(16, 16);
    logoLabel->setScaledContents(true);

    // 标题
    QLabel *titleLabel = new QLabel();
    titleLabel->setText(title);
    QFont titleFont = titleLabel->font();
    titleFont.setBold(true);
    titleLabel->setFont(titleFont);
    titleLabel->setObjectName("whiteLabel");

    // 最小化按钮
    //QPushButton *minButton = new QPushButton();
    QToolButton *minButton = new QToolButton();
    //minButton->setStyleSheet("QToolButton{color:white ; background-color: blue}");
    //QPixmap minPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMinButton);
    //minButton->setIcon(minPixmap);
    connect(minButton, SIGNAL(clicked()), this, SLOT(slotShowSmall()));

    // 最大化按钮
    maxButton_ = new QToolButton();
    //maxPixmap_ = this->style()->standardPixmap(QStyle::SP_TitleBarMaxButton);
    //restorePixmap_ = this->style()->standardPixmap(QStyle::SP_TitleBarNormalButton);
    maxButton_->setIcon(maxPixmap_);
    connect(maxButton_, SIGNAL(clicked()), this, SLOT(slotShowMaxRestore()));

    // 关闭按钮
    QToolButton *closeButton = new QToolButton();
    //QPixmap closePixmap = this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton);
    //closeButton->setIcon(closePixmap);
    connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));

    QHBoxLayout *titleLayout = new QHBoxLayout();
    titleLayout->addWidget(logoLabel);
    titleLayout->addWidget(titleLabel);
    titleLabel->setContentsMargins(5, 0, 0, 0);
    titleLayout->addStretch();
    titleLayout->addWidget(minButton, 0, Qt::AlignTop);
    titleLayout->addWidget(maxButton_, 0, Qt::AlignTop);
    titleLayout->addWidget(closeButton, 0, Qt::AlignTop);
    titleLayout->setSpacing(0);
    titleLayout->setContentsMargins(5, 0, 0, 0);

    QWidget *titleWidget = new QWidget();
    titleWidget->setLayout(titleLayout);
    titleWidget->installEventFilter(0);

    QVBoxLayout *mainLayout = new QVBoxLayout();
    mainLayout->addWidget(titleWidget);
    mainLayout->addWidget(contentWidget_);
    mainLayout->setSpacing(0);
    mainLayout->setMargin(5);
    this->setLayout(mainLayout);
}

void UserDefineFrame::slotShowSmall()
{
    this->showMinimized();
}

void UserDefineFrame::slotShowMaxRestore()
{
    if (isMax_) {
        this->showNormal();
        maxButton_->setIcon(maxPixmap_);
    } else {
        this->showMaximized();
        maxButton_->setIcon(restorePixmap_);
    }
    isMax_ = !isMax_;
}

void UserDefineFrame::mousePressEvent(QMouseEvent *e)
{
    startPos_ = e->globalPos();
    clickPos_ = e->pos();

    if (e->button() == Qt::LeftButton) {
        if (e->type() == QEvent::MouseButtonPress) {
            isPress_ = true;
        } else if (e->type() == QEvent::MouseButtonDblClick && e->pos().y() <= TITLE_HEIGHT) {
            this->slotShowMaxRestore();
        }
    }
}

void UserDefineFrame::mouseMoveEvent(QMouseEvent *e)
{
    if (isMax_ || !isPress_) {
        return;
    }
    this->move(e->globalPos() - clickPos_);
}

void UserDefineFrame::mouseReleaseEvent(QMouseEvent *)
{
    isPress_ = false;
}

bool UserDefineFrame::nativeEvent(const QByteArray & eventType, void * message, long * result)
{
    Q_UNUSED(eventType);
    const int HIT_BORDER = 5;
    const MSG *msg=static_cast<MSG*>(message);
    if(msg->message == WM_NCHITTEST) {
        int xPos = ((int)(short)LOWORD(msg->lParam)) - this->frameGeometry().x();
        int yPos = ((int)(short)HIWORD(msg->lParam)) - this->frameGeometry().y();
        if(this->childAt(xPos,yPos) == 0) {
            *result = HTCAPTION;
        } else {
            return false;
        }
        if(xPos > 0 && xPos < HIT_BORDER) {
            *result = HTLEFT;
        }
        if(xPos > (this->width() - HIT_BORDER) && xPos < (this->width() - 0)) {
            *result = HTRIGHT;
        }
        if(yPos > 0 && yPos < HIT_BORDER) {
            *result = HTTOP;
        }
        if(yPos > (this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
            *result = HTBOTTOM;
        }
        if(xPos > 0 && xPos < HIT_BORDER && yPos > 0 && yPos < HIT_BORDER) {
            *result = HTTOPLEFT;
        }
        if(xPos > (this->width() - HIT_BORDER) && xPos < (this->width() - 0) && yPos > 0 && yPos < HIT_BORDER) {
            *result = HTTOPRIGHT;
        }
        if(xPos > 0 && xPos < HIT_BORDER && yPos > (this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
            *result = HTBOTTOMLEFT;
        }
        if(xPos > (this->width() - HIT_BORDER) && xPos < (this->width() - 0) && yPos > (this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
            *result = HTBOTTOMRIGHT;
        }
        return true;
    }
    return false;
}

void UserDefineFrame::paintEvent(QPaintEvent *e)
{
    int border = FRAME_BORDER;
    if (this->isMaximized()) {
        border = 0;
    }

    QPainter painter(this);
    QPainterPath painterPath;
    painterPath.setFillRule(Qt::WindingFill);
    painterPath.addRect(border, border, this->width()-2*border, this->height()-2*border);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.fillPath(painterPath, QBrush(QColor(51,102,255,255)));
    QColor color(200, 200, 200);
    for (int i=0; i<border; i++) {
        color.setAlpha((i+1)*30);
        painter.setPen(color);
        painter.drawRect(border-i, border-i, this->width()-(border-i)*2, this->height()-(border-i)*2);
    }

    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(51,102,255,255));
    // 这里可以在资源中指定一张标题背景图片
    //painter.drawPixmap(QRect(border, border, this->width()-2*border, this->height()-2*border), QPixmap(DEFAULT_SKIN));
    painter.drawRect(QRect(border, TITLE_HEIGHT, this->width()-2*border, this->height()-TITLE_HEIGHT-border));

    QFrame::paintEvent(e);
}

使用举例(main.cpp)

#include "widget.h"
#include 
#include "userdefineframe.h"
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

//    QFile qssFile(":/qss/bluestyle.qss");

//    qssFile.open(QFile::ReadOnly);

//    QString qss;
//    if(qssFile.isOpen())
//    {
//        qss = QLatin1String(qssFile.readAll());
//        //qApp->setStyleSheet(qss);
//        qssFile.close();
//    }

    Widget *w = new Widget;

    UserDefineFrame frame(w, "CustomFrame");
    frame.show();
    //w.show();

    return a.exec();
}

你可能感兴趣的:(Qt)