Qt如何自定义滑动条

目录
  • 先放效果图
  • 1、头文件
  • 2、声明
  • 3、构造函数
  • 4、设置样式表
  • 5、重写鼠标点击事件
  • 6、重写鼠标释放事件
  • 7、绘制刻度
  • 8、实际使用

最近要用到滑动条,Qt自带的QSlider虽然能满足需求,但是操作起来有很多不舒服的地方,于是在它的基础上改了改,分享给大家使用。

先放效果图

在QSlider的基础上,改变了样式,绘制了刻度,增加了取整功能,只需要微调就能适应各种需求。

1、头文件

需要包含下面的东西

#include <QSlider>
#include <QtCore>
#include <QStylePainter>
#include <QStyleOptionSlider>
#include <QMouseEvent>

2、声明

需要继承QSlider,并重写两个鼠标事件mousePressEvent和mouseReleaseEvent,使用paintEvent用来绘制刻度线,使用信号发送选中的数值。

class MySlider : public QSlider
{
    Q_OBJECT
public:
    MySlider(QWidget *parent = nullptr);
    ~MySlider();

signals:
    void sliderValue(float);

private:
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void paintEvent(QPaintEvent *ev);
};

3、构造函数

首先在构造函数中配置控件的相关属性,在此宏定义的几个数值:nMin和nMax代表取值范围,nSingleStep代表步长,nTick代表刻度间隔,nWidth和nHeight控制控件的大小。

通过设置Orientation为Horizontal,使控件为横向。

#include "myslider.h"

int nMin = 0;
int nMax = 100;
int nSingleStep = 10;
int nTick = 10;     //修改刻度个数改此数值
int nWidth = 200;
int nHeight = 50;

MySlider::MySlider(QWidget *parent):
    QSlider (parent)
{
    setOrientation(Qt::Horizontal);
    setFixedSize(nWidth,nHeight);
    setMinimum(nMin);
    setMaximum(nMax);
    setSingleStep(nSingleStep);
    setTickInterval(nTick);
    setTickPosition(QSlider::TicksAbove);

4、设置样式表

QSlider::groove控制背景样式,QSlider::handle控制滑块样式,QSlider::sub-page控制划过区域的样式。

需要注意的是,qss和QSlider自带的刻度线并不兼容,使用qss就不能显示自带的刻度线了,但是后文我提供了解决方法。

setStyleSheet("QSlider::groove:horizontal{height:12px; left:0px; right:0px; border:0px; border-radius:6px; background:rgb(242,242,242);}    \
               QSlider::handle:horizontal{width:24px; background:#1644B0; border-radius:12px; margin:-6px 0px;}  \
               QSlider::sub-page:horizontal{background:#4C85FB; border:0px; border-radius:6px;}");
}

5、重写鼠标点击事件

之所以要这么做,是因为QSlider的点击效果是一格一格地移动,我希望滑块能直接跳到指定位置,所以需要用到setValue。

void MySlider::mousePressEvent(QMouseEvent * event)
{
    int pointPos = ((double)event->pos().x()) / (this->width() * (nMax - nMin) + nMin);
    if(pointPos != 0){
        if(abs(pointPos - this->value()) > nTick){
            this->setValue(pointPos);
        }
    }
    else{
        QSlider::mousePressEvent(event);
    }
}

6、重写鼠标释放事件

因为希望取值可以取几个固定的值,此处限定只能取0, 0.1, 0.2… 1这些值,所以在释放时对当前值四舍五入,然后让滑块移动到相应的位置。最后发出信号传递数值。

void MySlider::mouseReleaseEvent(QMouseEvent *event)
{
    //获取当前点击位置
    int currentX = event->pos().x();

    //获取当前点击的位置占整个Slider的百分比
    float per = currentX *1.0 /this->width();

    //限制边界
    if(per > 1) per = 1;
    else if(per < 0) per = 0;

    //按步长取整
    per = (float)(qRound(per * 100 / nTick) * nTick) / 100;

    //利用算得的百分比得到具体数字
    int value = per*(this->maximum() - this->minimum()) + this->minimum();

    //设定滑动条位置
    this->setValue(value);

    //滑动条移动事件等事件也用到了mousePressEvent,加这句话是为了不对其产生影响,是的Slider能正常相应其他鼠标事件
    QSlider::mousePressEvent(event);

    emit sliderValue(per);
}

7、绘制刻度

前文提到了qss和QSlider刻度的冲突,所以这里我们直接使用paintEvent画线。

修改宏定义的参数值,刻度的数量也会随之变动。

void MySlider::paintEvent(QPaintEvent *)
{
    QStylePainter p(this);
    QStyleOptionSlider opt;
    initStyleOption(&opt);

    // 获取滑块的大小
    QRect handle = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);

    // draw tick marks
    // do this manually because they are very badly behaved with style sheets
    int interval = tickInterval();
    if (interval == 0)
    {
        interval = pageStep();
    }

    if (tickPosition() != NoTicks)
    {
        for (int i = minimum(); i <= maximum(); i += interval)
        {
            int x = round((double)((double)((double)(i - this->minimum()) / (double)(this->maximum() - this->minimum())) * (double)(this->width() - handle.width()) + (double)(handle.width() / 2.0))) - 1;
            int h = 4;
            p.setPen(QColor("#a5a294"));
            if (tickPosition() == TicksBothSides || tickPosition() == TicksAbove)
            {
                int y = this->rect().top();
                p.drawLine(x, y, x, y + h);
            }
            if (tickPosition() == TicksBothSides || tickPosition() == TicksBelow)
            {
                int y = this->rect().bottom();
                p.drawLine(x, y, x, y - h);
            }
    }
        }
    // draw the slider (this is basically copy/pasted from QSlider::paintEvent)
    opt.subControls = QStyle::SC_SliderGroove;
    p.drawComplexControl(QStyle::CC_Slider, opt);
    // draw the slider handle
    opt.subControls = QStyle::SC_SliderHandle;
    p.drawComplexControl(QStyle::CC_Slider, opt);
}

8、实际使用

拖动或点击滑动条都会发出信号,传递滑块对应的值。

所以在要使用的地方建立信号槽,就可以接收对应滑动条传来的值并加以处理。

FaceThreshSlider = new MySlider(this);
connect(FaceThreshSlider, SIGNAL(sliderValue(float)), this, SLOT(setSlideThresh(float)));

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Qt之简单的异步操作实现方法

    目录 Qt简单的异步操作 Qt异步变同步问题 解决的问题 如何实现 代码块解析 Qt简单的异步操作 在实际应用中,经常会遇到一些耗时操作,导致了主线程的阻塞,这时候可以使用异步操作来避免阻塞. Qt的异步操作需要使用下面的库 #include <QtConcurrent/QtConcurrent> 然后将耗时操作丢进下面的函数中即可. QtConcurrent::run([=]()     {         func();     }); 如果需要判断耗时操作执行完毕与否,可以使用QFutu

  • Qt中简单的按钮槽函数传递参数方法

    目录 Qt按钮槽函数传递参数方法 Qt槽函数的几种用法 通过ui控件添加槽函数 通过connect连接 Qt按钮槽函数传递参数方法 Qt中一个典型的点击按钮触发槽函数的写法是: connect(btn, &QPushButton::clicked, this, &class::func); 当你希望在点击按钮后再向槽函数中传递参数,这种写法就无法做到了. 其原因是槽函数要和信号的参数完全对应,如果修改了传给槽函数的参数,点击按钮的信号就无法处理. 这里给出一个比较简单的传参方法,在信号槽中

  • QT中在QLabel显示图片并且利用鼠标点击画线问题

    目录 在QLabel显示图片并且利用鼠标点击画线 以下为我的代码,供参考 在QLabel显示图片并且利用鼠标点击画线 最近在做在Label上显示图片并且通过鼠标点击画线,在网上查了很多零零散散的东西,收获也多 很多初学者更希望直接贴代码,这样可以模仿来写,我下面直接贴出我的项目中自己写的maLabel类 (如果只是实现利用鼠标绘制, 重写void paintEvent(QPaintEvent *event);void mousePressEvent(QMouseEvent *e); void m

  • Qt 自定义属性Q_PROPERTY不显示float类型的解决

    目录 Qt 自定义属性Q_PROPERTY不显示float类型 Qt 自定义属性Q_PROPERTY 下面是一些典型的声明属性的示例 Demo Qt 自定义属性Q_PROPERTY不显示float类型 最近在学习编写自定义控件,其中使用到Q_PROPERTY来设置自定义属性. 查阅资料可以知道,Q_PROPERTY支持的类型可以是QVariant支持的任一类型,又或者是我们自定义的类型,其他是可选的.设置完之后,会在调用自定义控件的时候,在属性编辑表里看到我们的属性.如下图 但是,今天在使用中发

  • Qt如何自定义滑动条

    目录 先放效果图 1.头文件 2.声明 3.构造函数 4.设置样式表 5.重写鼠标点击事件 6.重写鼠标释放事件 7.绘制刻度 8.实际使用 最近要用到滑动条,Qt自带的QSlider虽然能满足需求,但是操作起来有很多不舒服的地方,于是在它的基础上改了改,分享给大家使用. 先放效果图 在QSlider的基础上,改变了样式,绘制了刻度,增加了取整功能,只需要微调就能适应各种需求. 1.头文件 需要包含下面的东西 #include <QSlider> #include <QtCore>

  • Qt界面中滑动条的实现方式

    目录 Qt界面实现滑动条 功能 效果 Qt滑动条解决点击和拖动问题 使用原QSlider 继承QSlider,重写事件函数 Qt界面实现滑动条 功能 在窗体内放置一个滑动条slider.一个spin box增减小控件,一个设置中间值的按钮,一个将当前值通过qQebug打印到编译器上.使用弹簧和布局使界面更美观. 效果 Widget.h文件: #pragma once #include <QtWidgets/QWidget> #include<QSlider> //滑动条头文件 #i

  • Android自定义View实现等级滑动条的实例

     Android自定义View实现等级滑动条的实例 实现效果图: 思路: 首先绘制直线,然后等分直线绘制点: 绘制点的时候把X值存到集合中. 然后绘制背景图片,以及图片上的数字. 点击事件down的时候,换小图片为大图片.move的时候跟随手指移动. up的时候根据此时的X计算最近的集合中的点,然后自动吸附回去. 1,自定义属性 <?xml version="1.0" encoding="utf-8"?> <resources> <de

  • 用jquery实现自定义风格的滑动条实现代码

    前些天我们学生在线首页改版,要做一个工具栏,由于版面的限制,原先策划的很多工具只好安排在一个小区域里面,具体效果如下: 当然,这样的效果,用html自带的控件也可以实现.不过自定义的话就可以自己设置滑动条的样式啦,比如说设为红色.蓝色等,按钮形状也可以自己做啦. 需要实现的效果是,这些工具一次最多在可见区域显示9个(这里假设工具项总数多于9个,不满9个的话,将来也很有可能扩展到9个),点击上下的按钮即可将可见区域内的工具区域上下移动. 但是这样做好后,运营人员给我提意见了:要是移动滑动条就可以实

  • Android自定义滑动验证条的示例代码

    本文介绍了Android自定义滑动验证条的示例代码,分享给大家,具体如下: *注:不知道为什么,h5的标签在这里没用了,所以我也只能用Markdown的语法来写了 项目地址:https://github.com/994866755/handsomeYe.seekbar.github.io 需求: 在我们的某些应用中需要滑动验证.比如说这个样子的: 刚开始我也很懵逼要怎么去弄,结果我去看了一些人的代码,有人是用自定义viewgroup去做,就是viewgroup包含滑动块和滑动条.但我觉得太麻烦,

  • Android自定义Seekbar滑动条 Pop提示跟随滑动按钮滑动

    本文实例为大家分享了Android自定义Seekbar滑动条的具体代码,供大家参考,具体内容如下 由于项目需要做出此效果,自定义写了一个. 效果图 思路: 原始的seekbar只有滑动条并没有下方的提示文字,所以我们必须要继承Seekbar重写这个控件. 代码: 在values文件夹下新建attrs.xml,用于设置跟随滑动按钮的文字大小,颜色,背景. <declare-styleable name="MySeekBar"> <attr name="text

  • Qt编写提示进度条的实现示例

    目录 一.前言 二.实现的功能 三.效果图 四.头文件代码 五.核心代码 六.控件介绍 一.前言 我们在很多的安装包中,在安装过程中,经常可以在底部看到一个漂亮的进度条,上面悬浮着显示对应的进度,然后底部进度多种颜色渐变展示,Qt自带的进度条或者操作系统的进度条样式,不够炫,这次索性直接来个自定义绘制实现,至于是继承QWidget类还是QProgressBar类,都无所谓,如果是继承自QWidget类的话,就需要自己设置最大值最小值范围值,而继承自QProgressBar的话就可以直接用自带的函

  • Android开发之拖动条/滑动条控件、星级评分控件功能的实例代码

    ProgressBar有2个子控件: SeekBar   拖动条控件 RatingBar   星级评分控件 1.拖动条控件 <SeekBar android:layout_width="300dp" android:layout_height="wrap_content" android:id="@+id/seekBar" android:min="0" android:max="100" andro

  • 使用Javascript开发sliding-nav带滑动条效果的导航插件

    本文介绍如何使用纯Javascript来开发一款简单的JS插件,本插件可以实现鼠标悬停在导航上时,下方的滑动条自动从当前菜单滑动到所选菜单当中去. 本项目的源代码寄宿于GitHub,记得点小星星哦: https://github.com/dosboy0716/sliding-nav 一.前言 效果如下图: 二.使用方法 本插件只需要如下的三步,就可以在您的项目中使用: 1.在</body>标记结束前,引用sliding-nav.js文件 2.在需要滑动条的菜单容器上加类名 sliding-na

  • C/C++ QT实现自定义对话框的示例代码

    对话框分为多种,常见的有通用对话框,自定义对话框,模态对话框,非模态对话框等,其中通用对话框包括了,QFileDialog文件对话框,QColorDialog颜色对话框,QFontDialog字体对话框,QInputDialog输入对话框等,自定义对话框则主要是实现自己布局的简单页面,区别于窗体对话框则显得更加简单一些,除对话框外,多窗体设计也是最常用的,例如多窗体嵌入,MID窗体等,下面则是每种窗体的代码总结. 创建自定义窗体 1.首先使用两个控件,TableView主要是表格处理,TreeV

随机推荐