当前位置: 首页 > article >正文

QMainwindow的鼠标跟踪事件不触发问题

一、无边框窗口实现代码

1.1 头文件

class EtcTestTool : public QMainWindow
{
	Q_OBJECT

public:
	EtcTestTool(QWidget *parent = Q_NULLPTR);
private:
	void InitialUi();
	//...
protected:
	void mousePressEvent(QMouseEvent*event)override;
	void mouseReleaseEvent(QMouseEvent*event)override;
	void mouseMoveEvent(QMouseEvent*event)override;
private:
	// 鼠标的 活动范围的枚举
	enum MousePosition
	{    /* 这里我们将一个窗口划分为9个区域,分别为
		左上角(1, 1)、中上(2,1)、右上角(3, 1)
		左中  (1, 2)、 中间(2, 2)、右中  (3, 2)
		左下角(1, 3)、中下(2,3)、 右下角(3, 3)
		10*x+y区分各个区域
		*/
		LeftTop = 11,
		Top = 21,
		RightTop = 31,
		Left = 12,
		Mid = 22,
		Right = 32,
		LeftBottom = 13,
		Bottom = 23,
		RightBottom = 33
	};
	//根据鼠标的设置鼠标样式,用于拉伸
	void SetMouseCursor(int x, int y);
	//判断鼠标的区域,用于拉伸
	int GetMouseRegion(int x, int y);
private:
	QPoint m_windowsLastPs;
	QPoint m_mouseLastPs;
	int m_mouse_press_region = MousePosition::Mid;
	QPoint m_dragStartPos;
	bool m_bPressing = false;

private:
	Ui::EtcTestToolClass ui;
};

1.2 实现文件


EtcTestTool::EtcTestTool(QWidget *parent)
	: QMainWindow(parent)
{
	
	setWindowFlags(Qt::FramelessWindowHint);
	ui.setupUi(this);
	InitialUi();
	//...
	
}


void EtcTestTool::InitialUi()
{
	//mainwindow的鼠标跟踪事件被子控件遮挡拦截
	this->setMouseTracking(true);
	ui.centralWidget->setMouseTracking(true);
	ui.frame->setMouseTracking(true);
	ui.frmTitle->setMouseTracking(true);
	ui.groupBox->setMouseTracking(true);
    //...
	
}


void EtcTestTool::on_btnMin_clicked()
{
	showMinimized();
}
void EtcTestTool::on_btnMax_clicked()
{
	if (isMaximized())
	{
		showNormal();
		ui.btnMax->setProperty("Max", false);
	}
	else
	{
		showMaximized();
		ui.btnMax->setProperty("Max", true);
	}
	ui.btnMax->style()->polish(ui.btnMax);
}

void EtcTestTool::on_btnClose_clicked()
{
	close();
}


void EtcTestTool::mousePressEvent(QMouseEvent*event)
{
	if (event->button() == Qt::LeftButton)
	{
		// 如果是鼠标左键
		// 获取当前窗口位置,以窗口左上角为标定
		m_windowsLastPs = pos();
		// 获取鼠标在屏幕的位置  就是全局的坐标 以屏幕左上角为坐标系
		m_mouseLastPs = event->globalPos();
		m_bPressing = true;
		m_mouse_press_region = GetMouseRegion(event->pos().x(), event->pos().y());
	}
	QWidget::mousePressEvent(event);
}

void EtcTestTool::mouseReleaseEvent(QMouseEvent*event)
{
	if (event->button() == Qt::LeftButton)
	{
		m_bPressing = false;
	}
	setCursor(QCursor{});
	QWidget::mousePressEvent(event);
}

void EtcTestTool::mouseMoveEvent(QMouseEvent*event)
{
	// 设置鼠标的形状
	SetMouseCursor(event->pos().x(), event->pos().y());
	// 计算的鼠标移动偏移量, 就是鼠标全局坐标 - 减去点击时鼠标坐标
	QPoint point_offset = event->globalPos() - m_mouseLastPs;
	if ((event->buttons() == Qt::LeftButton) && m_bPressing)
	{
		if (m_mouse_press_region == Mid)
		{
			// 如果鼠标是在窗口的中间位置,就是移动窗口
			move(m_windowsLastPs + point_offset);
		}
		else {
			// 其他部分 是拉伸窗口
			// 获取客户区
			QRect rect = geometry();
			switch (m_mouse_press_region)
			{
				// 左上角
			case LeftTop:
				rect.setTopLeft(rect.topLeft() + point_offset);
				break;
			case Top:
				rect.setTop(rect.top() + point_offset.y());
				break;
			case RightTop:
				rect.setTopRight(rect.topRight() + point_offset);
				break;
			case Right:
				rect.setRight(rect.right() + point_offset.x());
				break;
			case RightBottom:
				rect.setBottomRight(rect.bottomRight() + point_offset);
				break;
			case Bottom:
				rect.setBottom(rect.bottom() + point_offset.y());
				break;
			case LeftBottom:
				rect.setBottomLeft(rect.bottomLeft() + point_offset);
				break;
			case Left:
				rect.setLeft(rect.left() + point_offset.x());
				break;
			default:
				break;
			}
			setGeometry(rect);
			m_mouseLastPs = event->globalPos();
		}
	}
	QWidget::mousePressEvent(event);
}

void EtcTestTool::SetMouseCursor(int x, int y)
{
	// 鼠标形状对象
	Qt::CursorShape cursor{};
	int region = GetMouseRegion(x, y);
	switch (region)
	{
	case LeftTop:
	case RightBottom:
		cursor = Qt::SizeFDiagCursor; break;
	case RightTop:
	case LeftBottom:
		cursor = Qt::SizeBDiagCursor; break;
	case Left:
	case Right:
		cursor = Qt::SizeHorCursor; break;
	case Top:
	case Bottom:
		cursor = Qt::SizeVerCursor; break;
	caseMid:
		cursor = Qt::ArrowCursor; break;
	default:
		break;
	}
	setCursor(cursor);
}


int EtcTestTool::GetMouseRegion(int x, int y)
{
	int region_x = 0, region_y = 0;
	// 鼠标的X坐标小于 边界 说明他在最上层区域 第一区域
	if (x < kMouseBorderSize)
	{
		region_x = 1;
	}
	else if (x > (this->width() - kMouseBorderSize)) {
		region_x = 3;
	}
	else {
		region_x = 2;
	}
	if (y < kMouseBorderSize)
	{
		region_y = 1;
	}
	else if (y > (this->height() - kMouseBorderSize)) {
		region_y = 3;
	}
	else {
		region_y = 2;
	}
	return region_x * 10 + region_y;
}

二、鼠标移动事件无法触发

2.1 现象和原因

        Qt默认鼠标跟踪事件是关闭的,只有按下鼠标左键移动时才会触发;所以需要setMouseTracking(true)开启鼠标追踪事件。但是开启后仍然无法在不按左键情况下触发鼠标移动事件,后发现软件复写的QMainWindow的mouseMoveEvent函数,但是QMainWindow界面被centralWidget和布局的各种widget遮挡导致鼠标移动事件无法触发。

 

2.2 解决方案

解决方案:将QMainWindow的子控件centralWidget等同样开启鼠标跟踪事件setMouseTracking(true),则子控件的鼠标移动事件会通过事件循环传递到父类的QMainWindow中,最终触发QMainWindow的mouseMoveEvent函数。

void EtcTestTool::InitialUi()
{
    //mainwindow的鼠标跟踪事件被子控件遮挡拦截,
    this->setMouseTracking(true);
    ui.centralWidget->setMouseTracking(true);
    ui.frame->setMouseTracking(true);
    ui.frmTitle->setMouseTracking(true);
    ui.groupBox->setMouseTracking(true);
    //...
}


http://www.kler.cn/a/443128.html

相关文章:

  • 从CentOS到龙蜥:企业级Linux迁移实践记录(系统安装)
  • spark——RDD算子集合
  • Nacos server 2.4.0 版本已知问题和 Bug 汇总
  • 基于 Python 和 OpenCV 的人脸识别上课考勤管理系统
  • 【Unity功能集】TextureShop纹理工坊(十二)画笔工具、橡皮擦工具
  • 计算机网络之---局域网
  • C/C++ 匿名namespace和有名namespace的区别
  • 面试小札:闪电五连鞭_5
  • tryhackme-Pre Security-Defensive Security Intro(防御安全简介)
  • Parcel 常用插件:增强功能与性能的最佳选择
  • ASRPRO学习笔记二之语音控制LED亮灭
  • 鸿蒙操作系统简介
  • git 怎么删除一个远程分支
  • 代理IP与生成式AI:携手共创未来
  • 操作系统里的算法
  • k8s存储卷和动态创建pv
  • GaussDB 企业版轻量化部署探索(二)
  • 准备写一个内网穿透的工具
  • Redis--高并发分布式结构
  • Blazor(.razor)+VUE+elementUI适合一起用吗
  • ArcGIS地理空间平台manager存在任意文件读取漏洞
  • 开源流程引擎技术
  • SSM餐厅点餐系统--02635(免费领源码)可做计算机毕业设计JAVA、PHP、爬虫、APP、小程序、C#、C++、python、数据可视化、大数据、全套文案
  • 【OceanBase 诊断调优】—— OceanBase 数据库网络速率配置方案
  • 一个初始化bitmap的小算法
  • flask_sqlalchemy event监听查询事件