IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Qt开发-嵌入式里常用的滚动数字选择器 -> 正文阅读

[C++知识库]Qt开发-嵌入式里常用的滚动数字选择器

最近arm-linux环境设备机中应用软件需要做日期时间选择面板,要求做成滚动日期选择的样式如下图一,网上查找资料找到了一篇实现数字滚动选择的博客,对其进行修改补充实现了以下功能,本期只介绍数字滚动的实现,下期分享图一的实现。Qt 滚动选择学习_lg15273112290的博客-CSDN博客[参考链接](https://blog.csdn.net/BIG_C_GOD/article/details/52452631?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161648329416780271563953%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=1616483294167802715639https://blog.csdn.net/lg15273112290/article/details/115124797

? ? ? ? 图一 滚动日期选择

复现以上博主的代码时发现滑动太快有不居中的情况,如下图

?调试代码发现在数字矫正函数homing()里加上这句m_deviation=0;就可以使数字居中,以下为相关代码:

头文件中为:

#ifndef TIMESELECT_H
#define TIMESELECT_H

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

class timeSelect : public QWidget
{
    Q_OBJECT
public:
    explicit timeSelect(QWidget *parent = nullptr);
    ~timeSelect();
public:
    void setRange(int min, int max);//设置范围
    int readValue(); //获取当前值
    void setFormat(QString prefix,QString suffix);//设定显示格式,前缀和后缀
    void setCurValue(int Value);

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

    void paintEvent(QPaintEvent * m_painter);
    void paintNum(QPainter &painter,int num,int deviation,bool isMiddle); //绘制数字
    void homing(); //使选中的数字回到屏幕中间
    int  readDeviation(); //获取鼠标移动偏移量,默认为0
    void setDeviation(int n); //设置偏移量
private:
    int m_minRange; //最小值
    int m_maxRange; //最大值
    int m_currentValue; //当前选中的值
    bool isDragging; //鼠标是否按下
    int m_deviation; //偏移量,记录鼠标按下后移动的垂直距离
    int m_mouseSrcPos; //鼠标源X轴作标,用来计算偏移量
    int m_numSize; //计算所得的数字字符尺寸,以最长的情况为准
    bool isMiddle; //是否是中间的数字
    QString m_prefix;//显示格式前缀
    QString m_suffix;//显示格式后缀
    QPropertyAnimation *homingAni; //QPropertyAnimation 是一个控制动画效果的类



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



public slots:
};

#endif // TIMESELECT_H

具体函数文件.cpp的实现:

#include "timeselect.h"

timeSelect::timeSelect(QWidget *parent) :
    QWidget(parent),m_minRange(1),m_maxRange(50),
    m_currentValue(16),isDragging(0),m_deviation(0),
    m_numSize(6),isMiddle(false),m_prefix(""),m_suffix("")
{
    homingAni  = new QPropertyAnimation(this,""); //创建一个动画类
    homingAni->setDuration(300); //设置动画持续时间
    homingAni->setEasingCurve(QEasingCurve::OutQuad); //设置动画的缓动曲线,这里OutQuad是二次函数缓和曲线,减速到零速度

}

timeSelect::~timeSelect()
{

}
//设置范围
void timeSelect::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++;
    }
    update(); //重绘此组件,需要进行重绘时,要使用update

}
//获取当前值
int timeSelect::readValue()
{
    return m_currentValue;
}
//设置显示格式
void timeSelect::setFormat(QString prefix, QString suffix)
{
    m_prefix=prefix;
    m_suffix=suffix;
}
//设置当前显示
void timeSelect::setCurValue(int Value)
{
    //判断是否在有效区间内
    if(Value > m_maxRange)
    {
        Value=m_maxRange;
    }
    else if(Value < m_minRange)
    {
        Value=m_minRange;
    }
    m_currentValue=Value;
    if(this->isVisible())
    {
        update();
    }
}
//鼠标按下事件
void timeSelect::mousePressEvent(QMouseEvent *event)
{
    homingAni->stop(); //动画停止
    isDragging = true; //鼠标是否按下的标志位,布尔类型
    m_mouseSrcPos = event->pos().y(); //鼠标按下时候的y轴作标记录下来

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

           m_deviation = event->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)); //发出偏移量改变的信号,随着偏移量改变,重绘数字,就变成数字滚动的效果

           update();
       }

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

    QWidget::mouseReleaseEvent(event);
}
//绘图事件
void timeSelect::paintEvent(QPaintEvent *m_painter)
{
    QPainter painter(this); //创建画家类,指定绘图设备,也就是在哪画
    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--;
    }
    if(m_deviation <= -Height/5 && m_currentValue < m_maxRange) //同理,数字加一
    {
        m_mouseSrcPos -= Height/5;
        m_deviation += Height/5;
        m_currentValue++;
    }

    //中间数字
    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(5,39,175,120),4));
    painter.drawLine(0,Height/8*3,Width,Height/8*3);
    painter.drawLine(0,Height/8*5,Width,Height/8*5);

    QWidget::paintEvent(m_painter);
}
//画数字函数
void timeSelect::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)
    {
        painter.setPen(QColor(34,215,187,transparency)); //设置画笔,基色
    }
    else
    {
        painter.setPen(QColor(0,0,0,transparency)); //设置画笔,黑色
    }
    QString str_date;
    if(num<=9)
    {
        str_date=QString("0")+QString::number(num);
    }
    else
    {
        str_date=QString::number(num);
    }
    str_date=m_prefix+str_date+m_suffix;
    painter.drawText(QRectF(0,y,Width,height), //画文本,参数:QRectF参数:位置xy,长宽大小;对齐方式,中间对齐;内容
                     Qt::AlignCenter,
                     str_date);

}
//使选中的数字回到屏幕中间
void timeSelect::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++;
    }
    m_deviation=0;

    emit currentValueChanged(m_currentValue); //发送当前数值改变信号
    homingAni->start(); //开始动画
}
//获取鼠标移动偏移量
int timeSelect::readDeviation()
{
    return m_deviation;
}
//设置偏移量
void timeSelect::setDeviation(int n)
{
    m_deviation = n;
    update();
}

?最终实现的效果如下图,增加了几个显示接口,并使数字居中显示:

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-14 20:56:33  更:2022-02-14 20:56:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:29:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码