Qt 自定义通用标题栏TitleBar类

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值