Qt 之自定义界面(添加自定义标题栏)

转自:https://blog.csdn.net/liang19890820/article/details/50555298

简述

学习作者一去丶二三里关于Qt 之自定义界面的博客,自己参考作者的源码实现了自定义窗体界面,可控制窗体最小化、最大化、关闭的按钮。

Qt designer 设计界面控件效果

在这里插入图片描述

实现

customtitlewidget.h文件

#ifndef CUSTOMTITLEWIDGET_H
#define CUSTOMTITLEWIDGET_H

#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QEvent>
#include <QMouseEvent>
#include <QApplication>
#include <qt_windows.h>

namespace Ui {
class CustomTitleWidget;
}

class CustomTitleWidget : public QWidget
{
    Q_OBJECT

public:
    explicit CustomTitleWidget(QWidget *parent = 0);
    ~CustomTitleWidget();

    // 最大化/还原
    void updateMaximize();

protected:
    // 双击标题栏进行界面的最大化/还原
    virtual void mouseDoubleClickEvent(QMouseEvent *event);

    // 进行鼠界面的拖动
    virtual void mousePressEvent(QMouseEvent *event);

public slots:
    // 进行最小化、最大化/还原、关闭操作
    void slotClicked();

private:
    Ui::CustomTitleWidget *ui;
};

#endif // CUSTOMTITLEWIDGET_H

customtitlewidget.cpp文件

#include "customtitlewidget.h"
#include "ui_customtitlewidget.h"

CustomTitleWidget::CustomTitleWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::CustomTitleWidget)
{
    ui->setupUi(this);

    ui->label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    ui->maxBtn->setToolTip(tr("最小化"));
    ui->minBtn->setToolTip(tr("最大化"));
    ui->closeBtn->setToolTip(tr("关闭"));



    connect(ui->maxBtn, SIGNAL(clicked(bool)), this, SLOT(slotClicked()));
    connect(ui->minBtn, SIGNAL(clicked(bool)), this, SLOT(slotClicked()));
    connect(ui->closeBtn, SIGNAL(clicked(bool)), this, SLOT(slotClicked()));
}

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

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

        ui->maxBtn->setStyle(QApplication::style());
    }
}

void CustomTitleWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
    Q_UNUSED(event);

    emit ui->maxBtn->clicked();
}

void CustomTitleWidget::mousePressEvent(QMouseEvent *event)
{
    if (ReleaseCapture())
    {
        QWidget *pWindow = this->window();
        if (pWindow->isTopLevel())
        {
            SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
        }
    }
    event->ignore();
}

void CustomTitleWidget::slotClicked()
{
    QPushButton *pButton = qobject_cast<QPushButton *>(sender());
    QWidget *pWindow = this->window();
    if (pWindow->isTopLevel())
    {
        if (pButton == ui->minBtn)
        {
            pWindow->showMinimized();
        }
        else if (pButton == ui->maxBtn)
        {
            pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
        }
        else if (pButton == ui->closeBtn)
        {
            pWindow->close();
        }
    }
}

接口说明

mousePressEvent
之前,我们将界面移动的事件写在主界面里面,这会有一个问题,一般情况下,是界面随着标题栏的移动而移动,而并非界面中的所有位置都可以进行拖动,所以我们将事件写在标题栏中比较合理。

mouseDoubleClickEvent
双击标题栏会进行窗体的最大化/还原,所以我们需要重写此事件进行控制。

eventFilter

事件过滤器,这里被监听的窗体为标题栏所在的窗体,所以当窗体标题、图标等信息发生改变时,标题栏也应该随之改变。

最好不要通过直接调用接口的形式来操作对应的行为,比如:TitleBar中定义一个public函数来专门修改标题与图标,这样会造成不必要的麻烦,因为Qt本身就是基于事件的,所以此处采用过滤器的方式。

updateMaximize

因为窗体大小发生变化的时候,最大化的图标、提示应该对应的发生变化,所以在eventFilter中事件触发时调用。

使用方式

#include "widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{

    setWindowFlags(Qt::FramelessWindowHint | windowFlags());

    CustomTitleWidget *pTitleBar = new CustomTitleWidget(this);
    installEventFilter(pTitleBar);

    resize(400, 300);

    QPalette pal(palette());
    pal.setColor(QPalette::Background, QColor(180, 180, 176));
    setAutoFillBackground(true);
    setPalette(pal);

    QVBoxLayout *pLayout = new QVBoxLayout();
    pLayout->addWidget(pTitleBar);
    pLayout->addStretch();
    pLayout->setSpacing(0);
    pLayout->setContentsMargins(0, 0, 0, 0);
    setLayout(pLayout);
}

Widget::~Widget()
{

}

注意:
installEventFilter必须在setWindowTitle、setWindowIcon之前调用,因为必须先安装事件过滤器,相应事件触发时,才会进入标题栏的eventFilter事件中。

猜你喜欢

转载自blog.csdn.net/QIJINGBO123/article/details/86571282