Qt自定义通用标题栏TitleBar类
功能
- 自定义 Qt 通用标题栏,包含图标、标题、最小化、最大化、关闭;
- 支持设置最小化、最大化是否显示和是否可用;
- 支持拖动窗口;
- 图标、最小化、最大化、关闭控件的样式,支持通过应用程序的QSS文件设置,也可以通过修改TitleBar类的构造函数实现。
效果
实现
- 自定义TitleBar类继承自QWidget
- TitleBar类构造函数
TitleBar(QString title, QWidget* parent);
说明:title 用来设置标题 - TitleBar类声明signals
- void setMinEnabled(bool enable)
设置最小化按钮可用性 - void setMinVisible(bool visible)
设置最小化按钮可见性 - void setMaxEnabled(bool enable)
设置最大化按钮可用性 - void setMaxVisible(bool visible)
设置最大化按钮可见性
- TitleBar类重新QWidget如下函数
- virtual void painEvent(QPaintEvent*)
- virtual void mousePressEvent(QMouseEvent* event);
记录鼠标按下的标记m_pressed - virtual void mouseReleaseEvent(QMouseEvent* event);
清除鼠标按下的标记m_pressed - virtual void mouseDoubleClickEvent(QMouseEvent* event);
实现鼠标左键双击标题栏放大、缩小窗口 - virtual void mouseMoveEvent(QMouseEvent* event);
实现鼠标左键拖着窗口移动
- TitleBar类定义私有变量
- QWidget* m_parent;
保存父窗口,用于窗口移动、双击放大、缩小 - bool m_pressed;
保存鼠标左键是否按下,用于拖拽窗口 - QPoint m_move_pos;
保存鼠标左键移动位置,用于推拽窗口到指定位置
TitleBar类声明
#include <QWidget>
#include <QString>
#include <QPoint>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QTextCodec>
extern QTextCodec *codec;
#define TU codec->toUnicode
class TitleBar : public QWidget
{
Q_OBJECT
public:
TitleBar(QString title, QWidget *parent);
signals:
void setMinEnabled(bool enable);
void setMinVisible(bool visible);
void setMaxEnabled(bool enable);
void setMaxVisible(bool visible);
protected:
virtual void paintEvent(QPaintEvent *);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void mouseDoubleClickEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
private:
QWidget * m_parent;
bool m_pressed;
QPoint m_move_pos;
};
TitleBar类实现
#include "titlebar.h"
#include <QLabel>
#include <QHBoxLayout>
#include <QPushButton>
#include <QTextCodec>
#include <QFile>
#include <QStyleOption>
#include <QPainter>
#include <QStyle>
#include <QApplication>
QTextCodec *codec = QTextCodec::codecForName("utf-8");
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
TitleBar::TitleBar(QString title, QWidget *parent)
: QWidget(parent)
, m_parent(parent)
, m_pressed(false)
{
setMouseTracking(true);
setObjectName("TitleBar");
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
QLabel *title_icon = new QLabel(this);
title_icon->setObjectName("title_icon");
title_icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
QLabel *title_text = new QLabel(this);
title_text->setObjectName("title_text");
title_text->setText(title);
QPushButton *title_btn_min = new QPushButton(this);
title_btn_min->setObjectName("title_btn_min");
title_btn_min->setToolTip(TU("最小化"));
title_btn_min->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
connect(title_btn_min, &QPushButton::clicked, parent, &QWidget::showMinimized);
connect(this, &TitleBar::setMinEnabled, title_btn_min, &QPushButton::setEnabled);
connect(this, &TitleBar::setMinVisible, title_btn_min, &QPushButton::setVisible);
QPushButton *title_btn_max = new QPushButton(this);
title_btn_max->setObjectName("title_btn_max");
title_btn_max->setToolTip(TU("最大化"));
title_btn_max->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
connect(title_btn_max, &QPushButton::clicked, parent, &QWidget::showMaximized);
connect(this, &TitleBar::setMaxEnabled, title_btn_max, &QPushButton::setEnabled);
connect(this, &TitleBar::setMaxVisible, title_btn_max, &QPushButton::setVisible);
QPushButton *title_btn_close = new QPushButton(this);
title_btn_close->setObjectName("title_btn_close");
title_btn_close->setToolTip(TU("关闭"));
title_btn_close->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
connect(title_btn_close, &QPushButton::clicked, parent, &QWidget::close);
QHBoxLayout* title_h_layout = new QHBoxLayout(this);
title_h_layout->setSpacing(15);
title_h_layout->setContentsMargins(2, 2, 20, 2);
title_h_layout->addWidget(title_icon);
title_h_layout->addWidget(title_text);
title_h_layout->addStretch();
title_h_layout->addWidget(title_btn_min);
title_h_layout->addWidget(title_btn_max);
title_h_layout->addWidget(title_btn_close);
setLayout(title_h_layout);
QString qss;
qss.append("#title_icon{min-width: 20px; min-height: 15px; border-image: url(:/image/title_icon.png)}");
qss.append("#title_btn_min{min-width: 20px; min-height: 15px; border-image: url(:/image/min.png)}");
qss.append("#title_btn_max{min-width: 20px; min-height: 15px; border-image: url(:/image/max.png)}");
qss.append("#title_btn_close{min-width: 20px; min-height: 15px; border-image: url(:/image/close.png)}");
setStyleSheet(qss);
}
void TitleBar::paintEvent(QPaintEvent *event)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
QWidget::::paintEvent(event);
}
void TitleBar::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_pressed = true;
m_move_pos = event->globalPos() - m_parent->pos();
}
QWidget::mousePressEvent(event);
}
void TitleBar::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
m_pressed = false;
}
QWidget::mouseReleaseEvent(event);
}
void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
if (m_parent->isMaximized())
{
m_parent->showNormal();
}
else
{
m_parent->showMaximized();
}
// QWidget::mouseDoubleClickEvent(event);
}
void TitleBar::mouseMoveEvent(QMouseEvent *event)
{
QWidget::mouseMoveEvent(event);
if (m_pressed && (event->buttons() && Qt::LeftButton)
&& (event->globalPos() - m_move_pos).manhattanLength() > QApplication::startDragDistance())
{
m_parent->move(event->globalPos() - m_move_pos);
m_move_pos = event->globalPos() - m_parent->pos();
}
}
使用
// widget.h
#include <QWidget>
#include "titlebar.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget* parent = nullptr);
~Widget();
private:
Ui::WIdget *ui;
TitleBar* m_title_bar;
};
// widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
Widget::Widget(QWidget*parent)
: ui(new Ui::Widget)
{
ui->setupUi(this);
m_title_bar = new TitleBar("Hello", this);
QVBoxLayout* main_layout = new QVBoxLayout();
main_layout->setContentsMargins(2, 2, 2, 2);
main_layout->setSpacing(0);
main_layout->addWidget(m_title_bar);
main_layout->addStretch();
setLayout(m_title_bar);
}
Widget::~Widget()
{
delete ui;
}