QT笔记——QSlider滑动条滚轮事件和点击鼠标位置事件问题

news2024/11/14 17:56:39

需求:我们需要对一个滑动条 滚轮事件 和 点击到滑动条的位置 实时显示
问题:其中在做的时候遇到了很多的问题,一开始感觉很简单,现在将这些问题记录下来

ui图:
在这里插入图片描述
在这里插入图片描述

问题1:处理QSlider 滚轮事件的时候
这里有很大的问题,但是不知道原因,为什么会出现这样的原因,网上也没搜索到相关的内容

问题描述:我们在打印我们的滑动条的值的时候显示不正确
为了更加清楚显示值的变化,我加了值的显示(这个是测试需要,方便写笔记查看)

bool SliderWidget::eventFilter(QObject* watched, QEvent* event)
{
	if (ui.slider == watched)
	{
		if (event->type() == QEvent::Wheel)
		{
			QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
			ui.lineEdit1->setText(QString::number(m_index1));
			ui.lineEdit2->setText(QString::number(ui.slider->value()));
			ui.lineEdit3->setText(QString::number(ui.slider->sliderPosition()));
		}
	}
	return QWidget::eventFilter(watched, event);
}

不知道各位有没有看出这个滑动条的值出现了什么错误:
在这里插入图片描述
错误1:当我在向右滑动的时候,滑到最右边的时候,我再向滑动时,滑动条的值是在第10条分割线,上面显示的值: 10 ,实际应该的值:9
错误2:当我继续在向左滑动时,滑动条对应的值 都 对应不上了,上面显示的值 都比原来减少了1
错误3:当我滑动到最左边的时候,我 操控滑动条 从右 再 向左 , 上面的 值竟然从1-》2-》1,实际应该为 2-》1-》0

我的解决办法是:因为刻度总共有11个,通过滑动条 向前 向后 来改变index 的值

bool SliderWidget::eventFilter(QObject* watched, QEvent* event)
{
	if (ui.slider == watched)
	{
		if (event->type() == QEvent::Wheel)
		{
			//滚轮向前 
			if (wheelEvent->delta() > 0)
			{
				if (m_index1 >= 10)
				{
					m_index1 = 10;
				}
				else if (m_index1 < 10)
				{
					m_index1 += 1;
				}
			}
			else if (wheelEvent->delta() < 0)
			{
				if (m_index1 <= 0)
				{
					m_index1 = 0;
				}
				else if (m_index1 > 0)
				{
					m_index1 -= 1;
				}
			}
			
			//获取滑动条的值
			ui.lineEdit1->setText(QString::number(m_index1));
		}
	}
	return QWidget::eventFilter(watched, event);
}

结果如下:此时我获取的index 值时正确的,因为另外两个参数不是我需要的
在这里插入图片描述
问题2:处理QSlider 点击位置事件的时候
问题描述:我发现QSlider点击最后一个刻度的时候,非常的困难,基本上不可能到最后一个刻度(只通过点击的形式,不通过滑动条滚动的形式)

bool SliderWidget::eventFilter(QObject* watched, QEvent* event)
{
	if (ui.slider == watched)
	{
		if (event->type() == QEvent::MouseButtonRelease)
		{
			//根据鼠标点击的位置 来设置滑动条的 位置
			QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
			if (mouseEvent->button() == Qt::LeftButton)
			{ 
				int curValue = ui.slider->maximum() - ui.slider->minimum();
				int curPos = ui.slider->minimum() + curValue * (static_cast<double>(mouseEvent->x()) / ui.slider->width());

				ui.slider->setValue(curPos);
			}
		}
	}
	return QWidget::eventFilter(watched, event);
}

效果如下:我们发现 点击最后一个确实非常的困难
在这里插入图片描述
解决办法:

bool SliderWidget::eventFilter(QObject* watched, QEvent* event)
{
	if (ui.slider == watched)
	{
		if (event->type() == QEvent::MouseButtonRelease)
		{
			//根据鼠标点击的位置 来设置滑动条的 位置
			QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
			if (mouseEvent->button() == Qt::LeftButton)
			{ 
				int value = QStyle::sliderValueFromPosition(ui.slider->minimum(), ui.slider->maximum(), mouseEvent->pos().x(), ui.slider->width());
				ui.slider->setValue(value);
			}
		}
	}
	return QWidget::eventFilter(watched, event);
}

在这里插入图片描述
问题3:因为我的需求是 两个按钮共享一个滑动条,但是 两个 滑动条 有自己对应的index,此时我们就需要设置点击到自己的按钮的时候,设置index值

bool SliderWidget::eventFilter(QObject* watched, QEvent* event)
{
	if (ui.slider == watched)
	{
		if (event->type() == QEvent::Wheel)
		{
			//滚轮向前 
			if (wheelEvent->delta() > 0)
			{
				if (m_index1 >= 10)
				{
					m_index1 = 10;
				}
				else if (m_index1 < 10)
				{
					m_index1 += 1;
				}
			}
			else if (wheelEvent->delta() < 0)
			{
				if (m_index1 <= 0)
				{
					m_index1 = 0;
				}
				else if (m_index1 > 0)
				{
					m_index1 -= 1;
				}
			}
			
			//获取滑动条的值
			ui.lineEdit1->setText(QString::number(m_index1));
			qDebug() << "m_index:" << m_index1;
			//既然获取到了正确的m_index1 ,那么我们直接设置值应该没有问题吧(下面两种形式都不行,滑动条滑动的时候 会错乱,导致我们的index 错乱)	
			ui.slider->setValue((int)m_index1);
			//ui.slider->setSliderPosition(m_index);
		}
	}
	return QWidget::eventFilter(watched, event);
}

void SliderWidget::on_btn1_clicked()
{
	ui.slider->setValue(m_index1);
}

看一下下面的动图,很明显的就发现了问题
在这里插入图片描述
错误1:此时打乱了 我们原本正确的对应滑动条 的index 值,现在获取也不正确了
错误2:我们发现向前滑动一次 然后 向后 滑动一次 ,或者相反;滑动条的值 竟然跳了 2 个间隔,但是我在ui设置的时候只有1个间隔,这是肯定错误的,获取的值肯定是不正确的

解决办法:我就尝试不在事件过滤器里做操作,我在滑动条的ValueChanged事件中做操作

	connect(ui.slider, &QSlider::valueChanged, this, [=](int value) {
		ui.slider->setValue(value);
	
		if (ui.btn1->isChecked())
		{
			m_index1 = ui.slider->value();
			ui.lineEdit1->setText(QString::number(m_index1));
			qDebug() << "m_index1:" << m_index1;
		}
		else if (ui.btn2->isChecked())
		{
			m_index2 = ui.slider->value();
			ui.lineEdit1->setText(QString::number(m_index2));
			qDebug() << "m_index2:" << m_index2;
		}
		
	});

在这里插入图片描述
完整代码:
.h文件

#pragma once

#include <QWidget>
#include "ui_SliderWidget.h"
#include <QWheelEvent>
#include <QDebug>
#include <QPoint>
#include <QStyle>
#include <QSlider>

class SliderWidget : public QWidget
{
	Q_OBJECT

public:
	SliderWidget(QWidget* parent = Q_NULLPTR);
	~SliderWidget();

private:
	bool eventFilter(QObject* watched, QEvent* event);

public slots:
	void on_btn1_clicked();
	void on_btn2_clicked();

private:
	Ui::SliderWidgetClass ui;
	quint8 m_index1 = 5;
	quint8 m_index2 = 5;
};

.cpp文件

#include "SliderWidget.h"

SliderWidget::SliderWidget(QWidget* parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	ui.slider->installEventFilter(this);
	connect(ui.slider, &QSlider::valueChanged, this, [=](int value) {
		ui.slider->setValue(value);
	
		if (ui.btn1->isChecked())
		{
			m_index1 = ui.slider->value();
			ui.lineEdit1->setText(QString::number(m_index1));
		}
		else if (ui.btn2->isChecked())
		{
			m_index2 = ui.slider->value();
			ui.lineEdit1->setText(QString::number(m_index2));
		}
		
	});
}

SliderWidget::~SliderWidget()
{
}

bool SliderWidget::eventFilter(QObject* watched, QEvent* event)
{
	if (ui.slider == watched)
	{
		if (event->type() == QEvent::MouseButtonRelease)
		{
			//根据鼠标点击的位置 来设置滑动条的 位置
			QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
			if (mouseEvent->button() == Qt::LeftButton)
			{ 
				//int nDur = ui.slider->maximum() - ui.slider->minimum();
				//int nPos = ui.slider->minimum() + nDur * (static_cast<double>(mouseEvent->x()) / ui.slider->width());
				int value = QStyle::sliderValueFromPosition(ui.slider->minimum(), ui.slider->maximum(), mouseEvent->pos().x(), ui.slider->width());
				ui.slider->setValue(value);

				//m_index1 = value;
				//qDebug() << "m_index:" << m_index1;
				//qDebug() << "value:" << ui.slider->value();
				//qDebug() << "nPos:" << nPos;

				//m_index = value + 1;
				设定滑动条位置
				ui.slider->setValue(value);

				qDebug()<< "position:" << ui.slider->sliderPosition();
				qDebug() << "value:" << ui.slider->value();
				m_index = ui.slider->value();
				//ui.slider->setSliderPosition(value);
				//qDebug() << "m_index:" << m_index;
				//qDebug() << "positition:" << ui.slider->sliderPosition();
				//qDebug() << "value:" << ui.slider->value();

				//获取当前点击位置,得到的这个鼠标坐标是相对于当前QSlider的坐标
				//int currentX = mouseEvent->pos().x();
				//
				//qDebug() <<"currentX:" << currentX;
				获取当前点击的位置占整个Slider的百分比
				//double per = currentX * 1.0 / ui.slider->width();
				//qDebug() <<"width:" << ui.slider->width();
				利用算得的百分比得到具体数字
				//int value = per * (ui.slider->maximum() - ui.slider->minimum()) + ui.slider->minimum();
				//
				//if (value <= 0)
				//{
				// value = 0;
				//}
				//else if (value >= 10)
				//{
				// value = 10;
				//}
				//qDebug() << value;
				//m_index = value;
				//ui.slider->setValue(value);

			}
		}
		else if (event->type() == QEvent::Wheel)
		{
			QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
			//滚轮向前 
			if (wheelEvent->delta() > 0)
			{
				if (m_index1 >= 10)
				{
					m_index1 = 10;
				}
				else if (m_index1 < 10)
				{
					m_index1 += 1;
				}
			}
			else if (wheelEvent->delta() < 0)
			{
				if (m_index1 <= 0)
				{
					m_index1 = 0;
				}
				else if (m_index1 > 0)
				{
					m_index1 -= 1;
				}
			}

			ui.lineEdit1->setText(QString::number(m_index1));

			//m_index1 = ui.slider->sliderPosition();
			//ui.lineEdit2->setText(QString::number(ui.slider->value()));
			//ui.lineEdit3->setText(QString::number(ui.slider->sliderPosition()));
			//qDebug() << "m_index:" << m_index1;
			//qDebug() << "value:" << ui.slider->value();
			//qDebug() << "position:" << ui.slider->sliderPosition();
			
			//ui.slider->setValue((int)m_index1);
			//qDebug() << "value:" << ui.slider->value();
			//qDebug() << "value:" << ui.slider->value();
			//ui.slider->setSliderPosition(m_index);
			//qDebug() << ui.slider->sliderPosition();

		}
	}

	return QWidget::eventFilter(watched, event);
}

void SliderWidget::on_btn1_clicked()
{
	ui.slider->setValue(m_index1);
}

void SliderWidget::on_btn2_clicked()
{
	ui.slider->setValue(m_index2);
}

参考博客:
QSlider设置滚动块定位到鼠标点击的地方
Qt之QSlider介绍(属性设置、信号、实现滑块移动到鼠标点击位置)
Qt滑动条解决点击和拖动问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/67842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AlphaFold2源码解析(8)--模型之三维坐标构建

AlphaFold2源码解析(8)–模型之三维坐标构建 这个模块我们讲解AlphaFold的Structure module模块&#xff0c;该结构模块将蛋白质结构的抽象表示映射为具体的三维原子坐标。 Evoformer的单一表征被用作初始单一表征siinitial{s^{initial}_i }siinitial​&#xff0c;siinitial∈…

同步整流 降压恒流 输入4-40V 功率可达40W 电流3.6A 原理图

◆PCB 布线参考PCB 布局应遵循如下规则以确保芯片的正常工作。1:功率线包括地线&#xff0c;LX线和VIN线应该尽量做到短、 直和宽。2:输入电容应尽可能靠近芯片管脚&#xff08;VIN 和 &#xff09;。输入电源引脚可增加一个 0.1uF 的陶瓷电容以增强芯片的抗高频噪声能力。3:功…

小迪-day13(MySQL注入)

一、information_schema information_schema 数据库跟 performance_schema 一样&#xff0c;都是 MySQL 自带的信息数据库。其中 performance_schema 用于性能分析&#xff0c;而 information_schema 用于存储数据库元数据(关于数据的数据)&#xff0c;例如数据库名、表名、列…

信号和电源隔离的有效设计技术

介绍 如今&#xff0c;电子产品设计师比以往任何时候都更面临着一系列共同的目标&#xff1a;实现更高的吞吐量、更高的分辨率、更高效的系统和缩短上市时间。在工业自动化、医疗电子或电信系统等领域&#xff0c;通常需要电隔离多个信号&#xff0c;以使子系统能够共享数据或…

农民歌唱家大衣哥外出商演,大衣嫂在家晒麦子,真是一对金童玉女

在中国华语乐坛&#xff0c;曾经有很多对模范夫妻&#xff0c;比如说任静和付笛声&#xff0c;他们也是音乐领域的金童玉女。其实大家都忽略了一对夫妻&#xff0c;农民歌唱家大衣哥&#xff0c;和他的结发妻子玉华&#xff0c;同样是中国华语乐坛的骄傲。 只是因为大衣哥过于低…

计算机网络复习(一~三)

第一章 基本概念 1-01.计算机网络可以向用户提供哪些服务&#xff1f; 答&#xff1a;例如音频&#xff0c;视频&#xff0c;游戏等&#xff0c;但本质是提供连通性和共享这两个功能。连通性&#xff1a;计算机网络使上网用户之间可以交换信息&#xff0c;好像这些用户的计算…

RDPCrystal EDI SDK 10.0.4.X Crack

关于 RDPCrystal EDI 库 使用 .NET、NodeJS、JavaScript 或 .NET Core 创建、查看和验证 EDI 数据。 RDPCrystal EDI 库是一套 EDI 组件&#xff08;.NET、NodeJS/JavaScript 和 .NET Core&#xff09;&#xff0c;可以创建和操作任何 X12 标准文件。功能包括解析、连接、拆分、…

【Unity】填坑,Unity接入Epic Online Service上架Epic游戏商城

EOS SDK For Unity地址&#xff1a;https://github.com/PlayEveryWare/eos_plugin_for_unity_upm Epic是虚幻游戏引擎开发商&#xff0c;2018年12月Epic宣布推出Epic游戏商城至今刚好三年&#xff0c;Epic将平台分成定为12%(远低于当时Steam的30%)&#xff0c;并且频繁推出各种…

每天一个面试题:四种引用,弱引用防止内存泄漏

每天一个面试题&#xff1a;四种引用四种引用基本介绍实例Demo- 虚引用弱引用防止内存泄漏弱引用Debug分析源码开始全新的学习&#xff0c;沉淀才会有产出&#xff0c;一步一脚印&#xff01; 面试题系列搞起来&#xff0c;这个专栏并非单纯的八股文&#xff0c;我会在技术底层…

ZStack出品|制造业专属的VMware迁移方案长啥样?

导读&#xff1a;在国家大力推动信息技术自主化的背景下&#xff0c;制造业也在积极寻找自身信息化改革的路线。作为信息化技术的基石&#xff0c;虚拟化基础架构替换迫在眉睫。本文将从技术层面详细介绍VMware迁移至 ZStack Cloud 云平台的方案&#xff0c;助力制造业实现“信…

阿里P9整理分享的亿级流量Java高并发与网络编程实战PDF

前言 有人调侃我们说&#xff1a; 程序员不如送外卖。送外卖是搬运食物&#xff0c;自己是搬运代码&#xff0c;都不产出新的东西……透支体力&#xff0c;又消耗健康&#xff0c;可替代性极强&#xff0c;30岁之后就要面临被优化的危险……想跳槽&#xff0c;但是更高的平台…

云原生|kubernetes|使用cri-docker部署基于kubeadm-1.25.4的集群

前言&#xff1a; kubernetes的部署从1.24版本开始后&#xff0c;弃用docker-shim&#xff0c;也就是说部署1.24版本后的集群不能使用docker-ce了。 比较清晰的解决方案有两个&#xff0c;一是使用containerd&#xff0c;这个是一个新的支持cri标准的shim&#xff0c;一个是使…

opencv基础-印度小哥

基础课程 第一章-读取图片、视频和摄像头 Chapter 1 – Read Images Videos and Webcams图片放在程序所在文件夹下的Resources/test.png 1.1 opencv读取一张图片并显示&#xff1a; #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include …

Jmeter命令执行生成HTML格式报告详解

1、Dashboard&#xff08;概览仪表盘&#xff09; ①、Test and Report informations Test and Report informations&#xff1a;测试和报告信息: 测试结果保存文件/测试开始时间/测试结束时间/展示过滤器。 ②、APDEX (应用性能指标) APDEX(Application Performance Index)&am…

安装pangolin问题解决|找不到makefile

前提&#xff1a; 使用的系统为ubuntu18.04版本 遇到的问题&#xff1a; 问题一&#xff1a; 按照如下命令安装时出现了错误 git clone https://github.com/stevenlovegrove/Pangolin.git cd Pangolin mkdir build cd build cmake .. make -j4 sudo make install我用的cma…

vncserver远程管理kvm虚拟机

一、安装KVM 检查服务器是否支持虚拟化&#xff08;vmx为interl平台、svm是AMD平台&#xff09;&#xff1a; grep -E -o vmx|svm /proc/cpuinfo 安装KVM所需软件包&#xff1a; yum groupinstall kvm 或者&#xff1a; yum install kvm kmod-kvm qemu kvm-qemu-img virt…

数据链路层-点对点PPP(point-to-point protocal)

点对点协议ppp是目前使用最广泛的点对点数据链路层协议 用户通过连接运营商的isp&#xff0c;用的就是pppoe协议pppoe ppp over ethernet ppp协议为点对点数据链路层协议的数据报提供了一个标准方法 封装成帧链路控制协议LCP&#xff0c;主要用于建立&#xff0c;配置&#xf…

【面试题】JSON.stringify 和fast-json-stringify有什么区别

前言 相信大家对JSON.stringify并不陌生&#xff0c;通常在很多场景下都会用到这个API&#xff0c;最常见的就是HTTP请求中的数据传输&#xff0c; 因为HTTP 协议是一个文本协议&#xff0c;传输的格式都是字符串&#xff0c;但我们在代码中常常操作的是 JSON 格式的数据&…

Flink系列之Flink中Window原理及实践

title: Flink系列 一、Flink Window 概述 官网链接&#xff1a; https://nightlies.apache.org/flink/flink-docs-release-1.14/docs/dev/datastream/operators/windows/ 摘取一段话&#xff1a; Windows are at the heart of processing infinite streams. Windows split …

基于蒙特卡洛法的规模化电动车有序充放电及负荷预测(PythonMatlab实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f389;作者研究&#xff1a;&#x1f3c5;&#x1f3c5;&#x1f3c5;主要研究方向是电力系统和智能算法、机器学…