【QT学习】自定义标题栏

内容:

实现标题栏的自定义以及窗口缩放事件的重写。

自定义了一个标题栏类CommonTitleBar

.h文件

c++ 复制代码
#pragma once
#include <qwidget.h>
#include <qpushbutton.h>
#include <qlabel.h>
#include <QHBoxLayout>
#include <QEvent>
#include <QMouseEvent>
#include <QApplication>
#include <qframe.h>
#include <qdebug.h>
#include <qfile.h>
class CommonTitleBar :
    public QWidget
{
    Q_OBJECT
public:
    explicit CommonTitleBar(QWidget* parent = nullptr);
    void setTitleText(QString titleText);
    
private:
    QPushButton* _closeButton; //关闭按键
    QPushButton* _lockButton; //锁定按键
    QFrame* _partingLine; //分割线
    QLabel* _titleLabel; //显示标题

private slots:
    void slotCloseClicked(); //关闭按钮
    void slotLockClicked(); // 锁定按钮
};

.cpp文件

cpp 复制代码
#include "CommonTitleBar.h"
CommonTitleBar::CommonTitleBar(QWidget* parent) : QWidget(parent)
{
    //标题栏固定高度
    this->setFixedHeight(24);
    // 控件初始化
    _titleLabel = new QLabel(this);
    _closeButton = new QPushButton(this);
    _lockButton = new QPushButton(this);
    _partingLine = new QFrame(this);

    // label相关设置
    _titleLabel->setFixedHeight(23); // 固定高度
    // 让label在水平方向上扩展(充当弹簧,不用弹簧是因为弹簧没办法设置背景颜色)
    _titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    // 文字 水平居左 垂直居中
    _titleLabel->setAlignment(Qt::AlignLeft| Qt::AlignVCenter);
    // 字体大小 样式 加粗
    _titleLabel->setObjectName("CommonTitleBar_titleLabel");

    // 按钮相关设置
    // 设置关闭按钮 大小 图标 提示词 无边框
    _closeButton->setFixedSize(23, 23);
    _closeButton->setIcon(QIcon(":/icon/close.png"));
    _closeButton->setToolTip("关闭");
    // 设置名字 用于QSS样式表
    _closeButton->setObjectName("CommonTitleBar_closeButton");
    // 设置钉按钮 大小 图标 提示词 无边框
    _lockButton->setFixedSize(23, 23);
    _lockButton->setIcon(QIcon(":/icon/lock.png"));
    _lockButton->setToolTip("钉在桌面");
    _lockButton->setObjectName("CommonTitleBar_lockButton");
    // 分割线相关设置 
    // 高度固定为1   设为水平 
    _partingLine->setFixedHeight(1);
    _partingLine->setFrameShape(QFrame::HLine);
    // 分割线的颜色  rgb(36,36,38)
    _partingLine->setObjectName("CommonTitleBar_partingLine");
    // 控件布局 
    // 水平布局
    QHBoxLayout* horizontalLayout = new QHBoxLayout;
    horizontalLayout->setSpacing(0); //布局中控件之间的间隔(间隙)
    horizontalLayout->setContentsMargins(0, 0, 0, 0); //清除布局边距,即布局与其父容器边缘之间的空间
    horizontalLayout->addWidget(_titleLabel);
    horizontalLayout->addWidget(_lockButton);
    horizontalLayout->addWidget(_closeButton);
    // 垂直布局
    QVBoxLayout* verticalLayout = new QVBoxLayout;
    verticalLayout->setContentsMargins(0, 0, 0, 0); //清除布局边距
    verticalLayout->addLayout(horizontalLayout);
    verticalLayout->addWidget(_partingLine);
    this->setLayout(verticalLayout);
    //信号槽绑定
    connect(_closeButton, &QPushButton::clicked, this, &CommonTitleBar::slotCloseClicked);
    connect(_lockButton, &QPushButton::clicked, this, &CommonTitleBar::slotLockClicked);
}

// 设置标题显示内容
void CommonTitleBar::setTitleText(QString titleText)
{
    _titleLabel->setText(titleText);
}

// 关闭按钮
void CommonTitleBar::slotCloseClicked()
{
    this->window()->close();
}
// 锁定按钮
void CommonTitleBar::slotLockClicked()
{
    // 切换btnClose的锁定状态
    bool isLocked = _closeButton->isEnabled();

    _closeButton->setEnabled(!isLocked);

    if (isLocked) {
        _lockButton->setIcon(QIcon(":/icon/lockRed.png"));
    }
    else {
        _lockButton->setIcon(QIcon(":/icon/lock.png"));
    }
}

主界面里面实例化这个标题栏,同时将主界面的标题栏去掉

(注意,去掉之后窗口的缩放也就没有了,需要重写事件)

所以我们要在主界面中重写标题栏的一系列事件(关闭、移动)以及窗口的缩放事件。

.h文件

cpp 复制代码
#pragma once

#include <QtWidgets/QWidget>
#include "ui_LiveStreamMasterControl.h"
#include "CommonTitleBar.h"
#include "ServerListDisplay.h"
#include "ServerSync.h"
#include "ServerManagement.h"
#include "serverinfo.h"
#include <QList>
#include <QMap>
#include "networkmanager.h"
class LiveStreamMasterControl : public QWidget
{
    enum class EdgeBlockMark
    {
        EdgeBlockMarkInit = 0,
        EdgeBlockMarkRightDown,
        EdgeBlockMarkLeftDown
    };
    
    Q_OBJECT

public:
    LiveStreamMasterControl(QWidget *parent = nullptr);
    ~LiveStreamMasterControl();
    void loadStyleSheet(); //初始化控件样式

    //槽函数
    // 刷新服务器选择列表
    void soltServerSelectListRefresh();
    void soltUpdateProjectInfoForm();
    void ConstructUeData(ServerInfo& serverinfo, QString index);
private:
    Ui::LiveStreamMasterControlClass ui;
    // 自定义标题栏
    CommonTitleBar* _titleBar;
    // 关于鼠标事件
    EdgeBlockMark  _edgeMark = EdgeBlockMark::EdgeBlockMarkInit;// 边缘标记
    bool _isMousePressedEdge = false; // 鼠标是否在边界范围内被按下
    QPoint _mousePosition; //鼠标按下时的位置
    bool _isMousePressedTitle = false; //鼠标是否在标题栏中被按下
protected:
    void mousePressEvent(QMouseEvent* event); //鼠标按下
    void mouseMoveEvent(QMouseEvent* event); //鼠标移动
    void mouseReleaseEvent(QMouseEvent* event); //鼠标抬起
    // void resizeEvent(QResizeEvent*);//窗口重置大小

};

.cpp文件

cpp 复制代码
#include "LiveStreamMasterControl.h"

LiveStreamMasterControl::LiveStreamMasterControl(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
    // 开启鼠标跟踪  这个要开启 否则无法获得鼠标坐标
    this->setMouseTracking(true);
    //this->setStyleSheet("background-color: rgb(51,51,55); color: white;font-family: Microsoft YaHei; ");
    loadStyleSheet();// 加载qss样式
    // 去掉原边框及标题栏
    this->setWindowFlags(Qt::FramelessWindowHint);
    // 设置窗口大小
    this->setMinimumSize(QSize(913, 589));
	// 自定义标题栏
    _titleBar = new CommonTitleBar(this);
    _titleBar->setTitleText("  LiveStream");
	
	// 创建一个空窗口  然后使用一个布局把空窗口和标题栏添加进去
	// .....

	

}
// 鼠标按下事件
void LiveStreamMasterControl::mousePressEvent(QMouseEvent* event)
{
    int edgeSize = 10; //设置边缘范围

    if (event->button() == Qt::LeftButton) // 左键被按下
    {
        //判断鼠标点击坐标是否在标题栏中
        if (_titleBar->pos().x() <= event->pos().x() && _titleBar->pos().y() <= event->pos().y()
            && (_titleBar->pos().x() + _titleBar->width()) >= event->pos().x()
            && (_titleBar->pos().y() + _titleBar->height()) >= event->pos().y())
        {
            _mousePosition= event->pos();// 记录下鼠标的按下位置
            _isMousePressedTitle = true; // 鼠标在标题栏中被按下状态置为true
        }
        else if ((this->width() - edgeSize < event->pos().x()) && (event->pos().x() < this->width())
            && (this->height() - edgeSize < event->pos().y()) && (event->pos().y() < this->height()))// 右下角
        {
            _isMousePressedEdge = true;// 鼠标在边界范围中被按下状态置为true
            _edgeMark = EdgeBlockMark::EdgeBlockMarkRightDown;// 边缘标记为 右下角
        }
        else if ((0 < event->pos().x()) && (event->pos().x() < edgeSize)
            && (this->height() - edgeSize < event->pos().y()) && (event->pos().y() < this->height()))  //左下角
        {
            _isMousePressedEdge = true;// 鼠标在边界范围中被按下状态置为true
            _edgeMark = EdgeBlockMark::EdgeBlockMarkLeftDown; // 边缘标记为 左下角
        }
    }
}

// 鼠标移动事件
void LiveStreamMasterControl::mouseMoveEvent(QMouseEvent* event)
{
    int edgeSize = 10; //设置边缘范围
    
    // 鼠标在标题栏中被按下的情况
    if ((event->buttons() & Qt::LeftButton) &&  _isMousePressedTitle == true)
    {
        // 计算鼠标从按下时的位置(m_mousePosition)到当前位置(event->globalPos())的偏移量
        // 将窗口的位置移动到新的位置
        move(event->globalPos() - _mousePosition);
    }
    else if ((event->buttons() & Qt::LeftButton) && _isMousePressedEdge == true)// 鼠标在左/右下角中被按下的情况
    {
        if(_edgeMark == EdgeBlockMark::EdgeBlockMarkRightDown)
        {
            QRect rect = this->geometry(); //存储当前窗口部件的几何尺寸和位置
            rect.setBottom(this->mapToParent(event->pos()).y()); // 设置底部
            rect.setRight(this->mapToParent(event->pos()).x()); // 设置右侧
            this->setGeometry(rect); // 重新设置窗口的大小和尺寸
        }
        else if (_edgeMark == EdgeBlockMark::EdgeBlockMark::EdgeBlockMarkLeftDown)
        {
            QRect rect = this->geometry(); //存储当前窗口部件的几何尺寸和位置
            rect.setBottom(this->mapToParent(event->pos()).y()); // 设置底部
            rect.setLeft(this->mapToParent(event->pos()).x()); // 设置左侧
            this->setGeometry(rect); // 重新设置窗口的大小和尺寸
        }
    }
    else if ( (this->width() - edgeSize < event->pos().x()) && (event->pos().x() < this->width())
        && (this->height() - edgeSize < event->pos().y()) && (event->pos().y() < this->height()))  //右下角
    {
        this->setCursor(Qt::SizeFDiagCursor);// 设置光标变化
    }
    else if ((0 < event->pos().x()) && (event->pos().x() < edgeSize)
        && (this->height() - edgeSize < event->pos().y()) && (event->pos().y() < this->height()))  //左下角
    {
        this->setCursor(Qt::SizeBDiagCursor);// 设置光标变化
    }
    else if ((0 < event->pos().y()) && (event->pos().y() < this->height() - edgeSize))  // 中间部分
    {
        this->setCursor(Qt::ArrowCursor);// 恢复光标
    }
    else if ((this->height() - edgeSize < event->pos().y()) && (event->pos().y() < this->height())
        && (edgeSize < event->pos().x()) && (event->pos().x() < this->width() - edgeSize)) // 中间底部
    {
        this->setCursor(Qt::ArrowCursor);// 恢复光标
    }
}
// 鼠标释放事件
void LiveStreamMasterControl::mouseReleaseEvent(QMouseEvent* event)
{
    Q_UNUSED(event);
    _isMousePressedEdge = false;// 鼠标在边缘范围内按下状态置为false
    _isMousePressedTitle = false;// 鼠标在标题栏内被按下状态置为false
    _edgeMark = EdgeBlockMark::EdgeBlockMarkInit; // 边缘标记 初始化
}
相关推荐
未来之窗软件服务6 分钟前
sql速度优化多条合并为一条语句
数据库
山东布谷科技官方8 分钟前
布谷直播源码部署服务器关于数据库配置的详细说明
运维·服务器·数据库·直播系统源码·直播源码·直播系统搭建·直播软件开发
易云码28 分钟前
信息安全建设方案,网络安全等保测评方案,等保技术解决方案,等保总体实施方案(Word原件)
数据库·物联网·安全·web安全·低代码
newxtc34 分钟前
【客观理性深入讨论国产中间件及数据库-科创基础软件】
数据库·中间件·国产数据库·国产中间件·科创
懒惰才能让科技进步35 分钟前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
水月梦镜花36 分钟前
redis:list列表命令和内部编码
数据库·redis·list
7年老菜鸡40 分钟前
策略模式(C++)三分钟读懂
c++·qt·策略模式
love_and_hope1 小时前
Pytorch学习--神经网络--搭建小实战(手撕CIFAR 10 model structure)和 Sequential 的使用
人工智能·pytorch·python·深度学习·学习
Chef_Chen1 小时前
从0开始学习机器学习--Day14--如何优化神经网络的代价函数
神经网络·学习·机器学习
芊寻(嵌入式)1 小时前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习