QSlider使用笔记

最近做项目使用到QSlider滑动条控件,在使用过的过程中,发现一个问题就是点滑动条上的一个位置,滑块并没有移动到鼠标点击的位置,体验感很差,于是研究了下,让鼠标点击后滑块移动到鼠标点击的位置。
1、eventFilter采用事件过滤的方式:
给QSlider安装事件过滤器,重写事件过滤方法:
ui->hSliderAge->installEventFilter(this);

bool Dialog::eventFilter(QObject *watched, QEvent *event)
{if(ui->hSliderAge == watched && event->type() == QEvent::MouseButtonPress){QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);if(mouseEvent->button() == Qt::LeftButton){//方法1:
//            int curValue = ui->hSliderAge->maximum() - ui->hSliderAge->minimum();
//            int curPos = ui->hSliderAge->minimum() + curValue*(static_cast<double>(mouseEvent->x()) / ui->hSliderAge->width());
//            ui->hSliderAge->setValue(curPos);//方法2:int value = QStyle::sliderValueFromPosition(ui->hSliderAge->minimum(), ui->hSliderAge->maximum(), mouseEvent->pos().x(), ui->hSliderAge->width());ui->hSliderAge->setValue(value);}}return QDialog::eventFilter(watched, event);
}

运行效果:

这种方式是每个QSlider控件都要写到eventFilter函数里进行处理,如果有多个QSlider控件就会非常混乱,那有没有一种自定义控件的方式来实现这个功能,下面就介绍这种方法。

2、自定义QSlider控件实现点击效果。

#ifndef CUSTOMSLIDER_H
#define CUSTOMSLIDER_H#include <QSlider>class CustomSlider : public QSlider
{Q_OBJECT
public:explicit CustomSlider(QWidget *parent = nullptr);protected:void mousePressEvent(QMouseEvent *event) override;signals:};#endif // CUSTOMSLIDER_H
#include "customslider.h"
#include <QMouseEvent>
#include <QDebug>
#include <QStyle>CustomSlider::CustomSlider(QWidget *parent): QSlider{parent}
{}void CustomSlider::mousePressEvent(QMouseEvent *event)
{//获取当前点击位置,得到的这个鼠标坐标是相对于当前QSlider的坐标int currentX = event->pos().x();//获取当前点击的位置占整个Slider的百分比double per = currentX *1.0 / this->width();//利用算得的百分比得到具体数字int value = per*(this->maximum() - this->minimum()) + this->minimum();//int value2 = QStyle::sliderValueFromPosition(this->minimum(), this->maximum(), currentX, this->width());//double value3 = per*(this->maximum() - this->minimum()) + this->minimum();//设定滑动条位置this->setValue(value);//滑动条移动事件等事件也用到了mousePressEvent,加这句话是为了不对其产生影响,是的Slider能正常相应其他鼠标事件QSlider::mousePressEvent(event);
}

使用:

运行效果:

完整代码如下:

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACEclass Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();void initData();public slots:void slotValueChangedSliderAge(int value);void slotValueChangedSpinBoxAge(int value);void slotValueChangedSlider(int value);void slotValueChangedSpinBox(int value);protected:bool eventFilter(QObject *watched, QEvent *event) override;bool eventFilter2(QObject *watched, QEvent *event);private:Ui::Dialog *ui;
};
#endif // DIALOG_H
#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
#include <QMouseEvent>
#include <QStyle>Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{ui->setupUi(this);initData();
}Dialog::~Dialog()
{delete ui;
}void Dialog::initData()
{ui->hSliderAge->installEventFilter(this);ui->hSliderAge->setValue(18);ui->spinBoxAge->setValue(18);//设置步长ui->hSliderAge->setSingleStep(4);ui->hSlider->setSingleStep(4);ui->spinBoxAge->setSingleStep(4);ui->spinBox->setSingleStep(4);ui->hSliderAge->setRange(0, 115);ui->hSlider->setRange(0, 115);ui->spinBoxAge->setRange(0, 115);ui->spinBox->setRange(0, 115);//滑动条托动释放时触发信号ui->hSliderAge->setTracking(false);ui->hSlider->setTracking(false);connect(ui->hSliderAge, SIGNAL(valueChanged(int)), this, SLOT(slotValueChangedSliderAge(int)));connect(ui->spinBoxAge, SIGNAL(valueChanged(int)), this, SLOT(slotValueChangedSpinBoxAge(int)));connect(ui->hSlider, SIGNAL(valueChanged(int)), this, SLOT(slotValueChangedSlider(int)));connect(ui->spinBox, SIGNAL(valueChanged(int)), this, SLOT(slotValueChangedSpinBox(int)));
}void Dialog::slotValueChangedSliderAge(int value)
{ui->spinBoxAge->blockSignals(true);ui->spinBoxAge->setValue(value);ui->spinBoxAge->blockSignals(false);
}void Dialog::slotValueChangedSpinBoxAge(int value)
{ui->hSliderAge->blockSignals(true);ui->hSliderAge->setValue(value);ui->hSliderAge->blockSignals(false);
}void Dialog::slotValueChangedSlider(int value)
{ui->spinBox->blockSignals(true);ui->spinBox->setValue(value);ui->spinBox->blockSignals(false);
}void Dialog::slotValueChangedSpinBox(int value)
{ui->hSlider->blockSignals(true);ui->hSlider->setValue(value);ui->hSlider->blockSignals(false);
}bool Dialog::eventFilter(QObject *watched, QEvent *event)
{if(ui->hSliderAge == watched && event->type() == QEvent::MouseButtonPress){QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);if(mouseEvent->button() == Qt::LeftButton){//方法1:
//            int curValue = ui->hSliderAge->maximum() - ui->hSliderAge->minimum();
//            int curPos = ui->hSliderAge->minimum() + curValue*(static_cast<double>(mouseEvent->x()) / ui->hSliderAge->width());
//            ui->hSliderAge->setValue(curPos);//方法2:
//            int value = QStyle::sliderValueFromPosition(ui->hSliderAge->minimum(), ui->hSliderAge->maximum(), mouseEvent->pos().x(), ui->hSliderAge->width());
//            ui->hSliderAge->setValue(value);//方法3:eventFilter2(watched, event);}}return QDialog::eventFilter(watched, event);
}bool Dialog::eventFilter2(QObject *watched, QEvent *event)
{if(watched == ui->hSliderAge && event->type() == QEvent::MouseButtonPress){QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);//捕获左键按下if(mouseEvent->button() == Qt::LeftButton){int chunkLen{0};       //滑块宽度int sliderLen{0};      //滑槽宽度int mousePos{0};       //鼠标按下的位置//水平滑动条if(ui->hSliderAge->orientation() == Qt::Horizontal){chunkLen = ui->hSliderAge->minimumSizeHint().width();sliderLen = ui->hSliderAge->width();if(ui->hSliderAge->invertedAppearance()){mousePos = sliderLen - mouseEvent->x();}else{mousePos = mouseEvent->x();}}else{//垂直滑动条chunkLen = ui->hSliderAge->minimumSizeHint().height();sliderLen = ui->hSliderAge->height();if(ui->hSliderAge->invertedAppearance()){mousePos = sliderLen - mouseEvent->y();}else{mousePos = mouseEvent->y();}}if(sliderLen > chunkLen){//计算位置,设置滑动位置int curValue = ui->hSliderAge->maximum() - ui->hSliderAge->minimum();int sliderPos = ui->hSliderAge->minimum() +(int)(curValue * (mousePos - chunkLen/2.0)/(sliderLen - chunkLen));if(ui->hSliderAge->sliderPosition() != sliderPos){ui->hSliderAge->setSliderPosition(sliderPos);}}}}return QDialog::eventFilter(watched, event);
}

参考:
https://www.cnblogs.com/Gaaagaa/p/12130799.html
https://blog.csdn.net/lion_cxq/article/details/128212132
https://blog.csdn.net/qq_14945437/article/details/98730805

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ref和reactive, toRefs的使用

看尤雨溪说&#xff1a;为什么Vue3 中应该使用 Ref 而不是 Reactive&#xff1f; toRefs import { ref, toRefs } from vue;// 定义一个响应式对象 const state ref({count: 0,name: Vue });// 使用toRefs转换为响应式引用对象 const reactiveState toRefs(state);// 现在你…

二分查找------蓝桥杯

题目描述&#xff1a; 请实现无重复数字的升序数组的二分查找 给定一个元素升序的、无重复数字的整型数组 nums 和一个目标值 target&#xff0c;写一个函数搜索 nums 中的target&#xff0c;如果目标值存在返回下标 (下标从0 开始)&#xff0c;否则返回-1 数据范围: 0 < l…

【Linux系统化学习】进程等待

目录 进程等待 进程等待的必要性 进程等待的方法 wait方法 等待一个进程(阻塞等待&#xff09; waitpid方法 任意等待多个进程&#xff08;阻塞等待&#xff09; 父进程获取子进程的退出信息 非阻塞轮询等待 进程等待 进程等待的必要性 之前讲过&#xff0c;子进程退…

C++泛编程(3)

类模板基础 1.类模板的基本概念2.类模板的分文件编写3.类模板的嵌套 &#xff08;未完待续...&#xff09; 在往节内容中&#xff0c;我们详细介绍了函数模板&#xff0c;这节开始我们就来聊一聊类模板。C中&#xff0c;类的细节远比函数多&#xff0c;所以这个专题也会更复杂。…

Python实战:爬取小红书

有读者在公众号后台询问爬取小红书&#xff0c;今天他来了。 本文可以根据关键词&#xff0c;在小红书搜索相关笔记&#xff0c;并保存为excel表格。 爬取的字段包括笔记标题、作者、笔记链接、作者主页地址、作者头像、点赞量。 一、先看效果 1、爬取搜索页 2、爬取结果保存到…

【蓝桥杯冲冲冲】动态规划学习 [NOIP2003 提高组] 加分二叉树

【蓝桥杯冲冲冲】动态规划学习 [NOIP2003 提高组] 加分二叉树 蓝桥杯备赛 | 洛谷做题打卡day24 文章目录 蓝桥杯备赛 | 洛谷做题打卡day24[NOIP2003 提高组] 加分二叉树题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示数据规模与约定思路 题解代码我的一些话 [NOI…

【鸿蒙】大模型对话应用(四):页面发起请求实现对话能力

Demo介绍 本demo对接阿里云和百度的大模型API&#xff0c;实现一个简单的对话应用。 DecEco Studio版本&#xff1a;DevEco Studio 3.1.1 Release HarmonyOS SDK版本&#xff1a;API9 关键点&#xff1a;ArkTS、ArkUI、UIAbility、网络http请求、列表布局、层叠布局 定义接…

JAVA-File五个练习

下面习题思路大多都是&#xff1a; 1.获取路径下所有列表&#xff08;listfiles&#xff09;&#xff0c;2.遍历文件或文件夹&#xff08;增强for&#xff09;&#xff0c;3.判断是否是文件&#xff08;isFile&#xff09;并直接执行逻辑&#xff0c;4.判断当前是文件夹的情况&…

oc云渲染云渲染操作步骤

随着技术的飞速进步&#xff0c;云渲染已经日益成为一个主流的渲染选择。OC云渲染以其高效率、易用性和可靠性获得了广泛的认可和喜爱。尽管如此&#xff0c;对于刚入门的用户而言&#xff0c;掌握OC云渲染的正确方法可能仍旧是一项挑战。接下来&#xff0c;我们会详尽解释OC云…

vivado 手动设置自下而上的流量并导入网表、创建较低级别的网表

手动设置自下而上的流量并导入网表 要手动运行自下而上的流&#xff0c;请将较低级别的网表或第三方网表实例化为黑色盒子&#xff0c;Vivado工具在合成完成后将黑盒子融入完整的设计中。这个以下部分描述了该过程。 重要&#xff01;Vivado合成不合成或优化加密或非加密合成…

使用_NT_SYMBOL_PATH在启动VS前设置PDB路径

一、背景 由于公司相关项目的开发管理方式&#xff0c;导致公司会存在多个分支的版本正在开发/测试中。 在这样的背景下&#xff0c;我的日常工作中有时会出现存在某个分支的项目软件的某个功能出现了问题需要我去排查解决&#xff0c;而我当前并不在该分支上开发。于是只能安装…

AI重构千行百业!超声波俱乐部大湾区内部分享会圆满落幕

1月27日、28日&#xff0c;超声波俱乐部内部分享会第十六期、第十七期分别在深圳、广州召开&#xff0c;创梦天地、元气森林、新浪智库、百准、A2空间对活动进行了特别支持&#xff0c;六十余名AI领域的创始人和行业嘉宾出席分享会。 出席活动的嘉宾有&#xff1a; 超声波创始…