QT滚动数字 滚动选择器 滑动选择器

最近在做个小软件,用到定时提醒功能,定时选择时间的时候我想到了锤子手机的闹钟设置界面,当然这种数字滚动选择器也是很常见啦,类似下面的效果
在这里插入图片描述
参考了 http://blog.csdn.net/big_c_god/article/details/52452631
这个大佬的的demo是横向的,单个数字,数字左右移动切换
还有 https://blog.csdn.net/gdizcm/article/details/61915344
这个大佬的效果也是一条数字框,上下切换

借鉴了他们两个的代码,我做了个时钟选择器,效果是这样的
在这里插入图片描述
主要思路是先实现一条数字选择器,然后把他提升为一个类,管他叫timeSelect;用的时候new两个timeSelect类,new的时候可以把两个类的父类填成我们想要他显示的窗口。
代码挺多的,我不全贴啦,贴出最主要的,也就是滚动选择器的代码,基本上我都一一注释了

selectime.h

#ifndef SELECTTIME_H
#define SELECTTIME_H

#include <QWidget>
#include <QMouseEvent>
#include <QPainter>
#include <QPropertyAnimation>

namespace Ui {
class selectTime;
}

class selectTime : public QWidget
{
    Q_OBJECT

public:
    explicit selectTime(QWidget *parent = nullptr);
    ~selectTime();

public:
    void setRange(int min,int max); //设置范围
    int readValue(); //获取当前值

public:
    void mousePressEvent(QMouseEvent *);
    void mouseMoveEvent(QMouseEvent *);
    void mouseReleaseEvent(QMouseEvent *);
    //void wheelEvent(QWheelEvent *); //鼠标滚轮事件
    void paintEvent(QPaintEvent *);

    void paintNum(QPainter &painter,int num,int deviation,bool isMiddle); //绘制数字
    void homing(); //使选中的数字回到屏幕中间
    int  readDeviation(); //获取鼠标移动偏移量,默认为0
    void setDeviation(int n); //设置偏移量

signals:
    void currentValueChanged(int value); //当前数值改变信号
    void deviationChange(float deviation); //偏移量改变信号


public:
    int m_minRange; //最小值
    int m_maxRange; //最大值
    int m_currentValue; //当前选中的值
    bool isDragging; //鼠标是否按下
    int m_deviation; //偏移量,记录鼠标按下后移动的垂直距离
    int m_mouseSrcPos; //鼠标源X轴作标,用来计算偏移量
    int m_numSize; //计算所得的数字字符尺寸,以最长的情况为准
    bool isMiddle; //是否是中间的数字
    QPropertyAnimation *homingAni; //QPropertyAnimation 是一个控制动画效果的类

private:
    Ui::selectTime *ui;
};

#endif // SELECTTIME_H

selectime.cpp

#include "selecttime.h"
#include "ui_selecttime.h"
#include <QDebug>

selectTime::selectTime(QWidget *parent) :
    QWidget(parent),m_minRange(1),m_maxRange(24),
    m_currentValue(16),isDragging(0),m_deviation(0),m_numSize(6),isMiddle(0),
    ui(new Ui::selectTime)
{
    ui->setupUi(this);

    homingAni  = new QPropertyAnimation(); //创建一个动画类
    homingAni->setDuration(300); //设置动画持续时间
    homingAni->setEasingCurve(QEasingCurve::OutQuad); //设置动画的缓动曲线,这里OutQuad是二次函数缓和曲线,减速到零速度
}

selectTime::~selectTime()
{
    delete ui;
}

//设置范围
void selectTime::setRange(int min,int max)
{
    m_minRange = min;
    m_maxRange = max;

    if(m_currentValue < min) //如果选中的当前值小于最小值,就等于最小值,不会再减了
        m_currentValue = min;
    if(m_currentValue > max) //最大值同理
        m_currentValue = max;

    //计算字符尺寸
    m_numSize = 3;
    int temp = m_maxRange;
    while(temp > 0)
    {
        temp /= 10;
        m_numSize++;
    }

    repaint(); //重绘此组件,需要进行重绘时,要使用repaint
}

//获取当前值
int selectTime::readValue()
{
    return m_currentValue;
}

//鼠标按下事件
void selectTime::mousePressEvent(QMouseEvent *e)
{
    homingAni->stop(); //动画停止
    isDragging = 1; //鼠标是否按下的标志位,布尔类型
    m_mouseSrcPos = e->pos().y(); //鼠标按下时候的y轴作标记录下来
}

//鼠标移动事件
void selectTime::mouseMoveEvent(QMouseEvent *e)
{
    if(isDragging)
    {
        //数值到边界时,阻止继续往对应方向移动
        if((m_currentValue == m_minRange && e->pos().y() >= m_mouseSrcPos)||
          (m_currentValue == m_maxRange && e->pos().y() <= m_mouseSrcPos))
            return;

        m_deviation = e->pos().y() - m_mouseSrcPos; //垂直偏移量 = 现在的坐标 - 开始的作标

        //若移动速度过快时进行限制
        if(m_deviation > (height()-1)/5)
            m_deviation = (height()-1)/5;
        else if(m_deviation < -(height()-1)/5)
            m_deviation = -(height()-1)/5;

        emit deviationChange((float)m_deviation/((height()-1)/5)); //发出偏移亮改变的信号,随着偏移量改变,重绘数字,就变成数字滚动的效果

        repaint();
    }
}

//鼠标松开事件
void selectTime::mouseReleaseEvent(QMouseEvent *)
{
    if(isDragging) //如果鼠标松开了,那么还原一下鼠标按下标志位
    {
        homing(); //使选中的数字回到屏幕中间
        isDragging = 0;
    }
}

//绘图事件
void selectTime::paintEvent(QPaintEvent *)
{
    QPainter painter(this); //创建画家类,指定绘图设备,也就是在哪画
    //painter.begin(ui->hour); //给画家类,重新指定绘图设备,也就是在哪显示
    painter.setRenderHint(QPainter::Antialiasing, true); //反走样,就是抗锯齿

    int Width = width()-1; //设置宽高
    int Height = height()-1;

    if(m_deviation >= Height/5 && m_currentValue > m_minRange) //偏移量大于1/4 高的时候,数字减一
    {
        m_mouseSrcPos += Height/5; //鼠标起始位置重新设置,即加上1/4的高度
        m_deviation -= Height/5; //偏移量重新设置,即减去1/4的高度
        m_currentValue -= 1;
    }
    if(m_deviation <= -Height/5 && m_currentValue < m_maxRange) //同理,数字加一
    {
        m_mouseSrcPos -= Height/5;
        m_deviation += Height/5;
        m_currentValue += 1;
    }

    //中间数字
    paintNum(painter,m_currentValue,m_deviation,isMiddle=1); //将选中数字画到中间

    //两侧数字1
    if(m_currentValue != m_minRange) //选中的数字不是最小,不是最大,那么就有两侧数字,然后画出两侧数字
        paintNum(painter,m_currentValue-1,m_deviation-Height*2/10,isMiddle=0);
    if(m_currentValue != m_maxRange)
        paintNum(painter,m_currentValue+1,m_deviation+Height*2/10,isMiddle=0);

    //两侧数字2,超出则不显示
    if(m_deviation >= 0 && m_currentValue-2 >= m_minRange)
        paintNum(painter,m_currentValue-2,m_deviation-Height*4/10,isMiddle=0);
    if(m_deviation <= 0 && m_currentValue+2 <= m_maxRange)
        paintNum(painter,m_currentValue+2,m_deviation+Height*4/10,isMiddle=0);

    //画边框,中间数字两侧的边框
    painter.setPen(QPen(QColor(0,0,0,120),2));
    painter.drawLine(0,Height/8*3,Width,Height/8*3);
    painter.drawLine(0,Height/8*5,Width,Height/8*5);

}

//画数字函数
void selectTime::paintNum(QPainter &painter,int num,int deviation,bool isMiddle)
{
    int Width = this->width()-1;
    int Height = this->height()-1;

    int size = (Height - qAbs(deviation))/m_numSize; //qAbs 返回输入参数对应类型的绝对值。
    int transparency = 255-510*qAbs(deviation)/Height; //设置透明度
    int height = Height/2-3*qAbs(deviation)/5;
    int y = Height/2+deviation-height/2;

    QFont font;
    font.setPixelSize(size); //设置像素大小
    painter.setFont(font); //设置字体
    if(isMiddle == true){
        painter.setPen(QColor(34,215,187,transparency)); //设置画笔,基色
    }else{
        painter.setPen(QColor(0,0,0,transparency)); //设置画笔,黑色
    }
    painter.drawText(QRectF(0,y,Width,height), //画文本,参数:QRectF参数:位置xy,长宽大小;对齐方式,左对齐;内容
                     Qt::AlignCenter,
                     QString::number(num));
}

//使选中的数字回到屏幕中间
void selectTime::homing()
{
    //将数字矫正到中心
    if(m_deviation > height()/20)
    {
        homingAni->setStartValue((height()-1)/8-m_deviation);
        homingAni->setEndValue(0);
        m_currentValue--;
    }
    else if(m_deviation > -(height())/20)
    {
        homingAni->setStartValue(m_deviation);
        homingAni->setEndValue(0);
    }
    else if(m_deviation < -(height())/20)
    {
        homingAni->setStartValue(-(height()-1)/8-m_deviation);
        homingAni->setEndValue(0);
        m_currentValue++;
    }
    emit currentValueChanged(m_currentValue); //发送当前数值改变信号
    homingAni->start(); //开始动画
}

//获取鼠标移动偏移量
int selectTime::readDeviation()
{
    return m_deviation;
}

//设置偏移量
void selectTime::setDeviation(int n)
{
    m_deviation = n;
    repaint();
}

这是滚动显示的代码,效果是下面这样
在这里插入图片描述
如果想要完整的选择时间的效果,去下面这里下载吧,代码有点多我就不贴啦,为了生计1个积分不过分吧,体谅体谅

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
Qt6是一款流行的跨平台开发工具,可以用于编写实时示波器程序。实时示波器能够采集和显示电信号或其他类型的实时数据,可用于调试和诊断各种电子、电气和机械系统。下面给出一个实时示波器程序的编写思路。 1. 定义采样率和采样精度。示波器的效果和响应速度取决于采样率和采样精度,因此需要根据所需的应用场景进行选择。 2. 选择合适的数据输入设备和数据传输方式。可以使用网络接口、串口或USB设备等手段来获取数据,并通过Qt提供的数据传输库进行数据传输。 3. 定义数据显示界面。实时示波器的核心是数据的实时显示,Qt提供了多种界面元素,如窗口、控件和布局等,可用于设计各种数据显示和控制界面。 4. 利用Qt提供的图形绘制和显示功能,在画布上绘制波形图。可以采用多种绘图方式,如折线图、散点图和柱状图等,同时还可添加坐标轴、标签和注释等图形元素,以方便用户观察和分析数据。 5. 设计用户界面的交互行为。可以通过按钮、滑动条等控件实现数据显示的控制,如选择采样率、采样精度和数据范围等。 6. 添加数据处理和分析功能。实时示波器通常需要进行数据处理和分析,如滤波、峰值检测、FFT变换等,以方便用户获取更多的有用信息。 7. 最后进行优化和测试,以保证程序的可靠性和性能。 综上所述,Qt6可以用于开发实时示波器程序,并且可以根据需要进行灵活的定制和扩展。欢迎有需要的用户进行尝试和应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值