Qt 之自定义界面(添加自定义标题栏)
转自:https://blog.****.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事件中。