内容:
实现标题栏的自定义以及窗口缩放事件的重写。
自定义了一个标题栏类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; // 边缘标记 初始化
}