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

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

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);
			//static int index = 5;
			//滚轮向前 
			if (wheelEvent->delta() > 0)
			{
				if (ui.btn1->isChecked())
				{
					if (m_index1 >= 10)
					{
						m_index1 = 10;
					}
					else if (m_index1 < 10)
					{
						m_index1 += 1;
					}
				}
				else if (ui.btn2->isChecked())
				{
					if (m_index2 >= 10)
					{
						m_index2 = 10;
					}
					else if (m_index2 < 10)
					{
						m_index2 += 1;
					}
				}

			}
			else if (wheelEvent->delta() < 0)
			{
				if (ui.btn1->isChecked())
				{
					if (m_index1 <= 0)
					{
						m_index1 = 0;
					}
					else if (m_index1 > 0)
					{
						m_index1 -= 1;
					}
				}
				else if (ui.btn2->isChecked())
				{
					if (m_index2 <= 0)
					{
						m_index2 = 0;
					}
					else if (m_index2 > 0)
					{
						m_index2 -= 1;
					}
				}

			}
			if (ui.btn1->isChecked())
			{
				ui.lineEdit1->setText(QString::number(m_index1));
			}
			else if (ui.btn2->isChecked())
			{
				ui.lineEdit1->setText(QString::number(m_index2));
			}

			//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滑动条解决点击和拖动问题

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!感谢您的提问! 要自定义QSlider滑动,可以使用Qt样式表(QSS)。以下是一个示例代码,演示如何将QSlider滑动和边框样式定制为圆形和阴影效果: ```python # -*- coding: utf-8 -*- from PyQt5.QtWidgets import QApplication, QWidget, QSlider from PyQt5.QtGui import QPainter from PyQt5.QtCore import Qt class MySlider(QSlider): def __init__(self, parent=None): super().__init__(parent) self.setStyleSheet(''' QSlider::groove:horizontal { border: none; height: 4px; background-color: rgba(255, 255, 255, 150); border-radius: 2px; } QSlider::sub-page:horizontal { background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0, stop: 0 rgba(255, 255, 255, 200), stop: 1 rgba(255, 255, 255, 0)); border-radius: 2px; } QSlider::handle:horizontal { width: 10px; margin-top: -3px; margin-bottom: -3px; border-radius: 5px; background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #f6f7fa, stop:1 #dadbde); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35); } QSlider::handle:horizontal:hover { background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #dadbde, stop:1 #f6f7fa); } QSlider::handle:horizontal:pressed { background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #dadbde, stop:1 #f6f7fa); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.35); } ''') def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.translate(0, self.height() / 2) painter.setPen(Qt.NoPen) # Draw border shadow = QtGui.QRadialGradient(0, 0, 60, 0, 0) shadow.setColorAt(0, QtGui.QColor(0, 0, 0, 50)) shadow.setColorAt(1, QtGui.QColor(0, 0, 0, 0)) painter.setBrush(QtGui.QBrush(shadow)) painter.drawEllipse(-32, -32, self.width() + 64, self.width() + 64) # Draw circle painter.setBrush(QtGui.QColor(255, 255, 255)) painter.drawEllipse(self.rect().adjusted(20, 20, -20, -20)) # Draw slider handle self.drawSliderHandle
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值