Qt自绘简单数字滚动选择控件

效果图:

功能说明:该控件主要是通过鼠标左键点击后上下移动的同时,数字跟随滚动,鼠标松开时则选中中间的数字。(因不会录制动图,功能就简单文字说明了0.0)。

设计思路:设计该控件思路主要分三部分,第一是先标定两条临界线;第二时绘制4个数字显示的rect区域,图中只显示三个,还有一个则是绘制在显示区域外,根据鼠标是上划还是下划来确定初始的显示位置是在上方还是在下方;第三是重载鼠标事件,然后根据鼠标的移动来进行滚动绘制。

第一步和第二步主要代码逻辑如下:


void TimeSelectWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    
    // 绘制背景
    painter.save();
    painter.setBrush(QColor(0, 0, 0, 100));
    painter.drawRoundedRect(rect(), 5, 5);
    painter.restore();

    // 鼠标上划,Y轴值固定每次移动减2,然后在判读每一个处于最顶端(Y坐标为0)的矩形Y坐标是否小于
    // 0,当小于零时处于最下方显示区域外的第4个矩形显示区域开始向上移动,以此形成循环滚动的视觉
    // 效果
    if(!m_curValueFlag)
    {
        if(m_firstY <= 0)
        {
            if(!m_pressFlag)
            {
                if(m_firstY  <= -height() / 3 / 2)
                {
                    m_firstY = height();
                    m_secendY = 0;
                    m_thridY = height() / 3;
                    m_fourY = height() / 3 * 2;

                    m_firstValue = m_fourValue + 1;
                    if(m_firstValue > m_maxValue)
                    {
                        m_firstValue = 0;
                    }
                    painterNum(&painter, m_secendY, m_thridY, m_fourY, m_firstY,
                               m_secendValue, m_thridValue, m_fourValue, m_firstValue);
                }
                else
                {
                    m_firstY = 0;
                    m_secendY = height() / 3;
                    m_thridY = height() / 3 * 2;
                    m_fourY = height();

                    painterNum(&painter, m_firstY, m_secendY, m_thridY, m_fourY,
                               m_firstValue, m_secendValue, m_thridValue, m_fourValue);
                }
            }
            else
            {
                painterNum(&painter, m_firstY, m_secendY, m_thridY, m_fourY,
                           m_firstValue, m_secendValue, m_thridValue, m_fourValue);
            }
        }
        if(m_secendY <= 0)
        {
            if(!m_pressFlag)
            {
                if(m_secendY  <= -height() / 3 / 2)
                {
                    m_firstY = height() / 3 * 2;
                    m_secendY = height();
                    m_thridY = 0;
                    m_fourY = height() / 3;
                    m_secendValue = m_firstValue + 1;
                    if(m_secendValue > m_maxValue)
                    {
                        m_secendValue = 0;
                    }

                    painterNum(&painter, m_thridY, m_fourY, m_firstY, m_secendY,
                               m_thridValue, m_fourValue, m_firstValue, m_secendValue);

                }
                else
                {
                    m_firstY = height();
                    m_secendY = 0;
                    m_thridY = height() / 3;
                    m_fourY = height() / 3 * 2;

                    painterNum(&painter, m_secendY, m_thridY, m_fourY, m_firstY,
                               m_secendValue, m_thridValue, m_fourValue, m_firstValue);
                }
            }
            else
            {
                painterNum(&painter, m_secendY, m_thridY, m_fourY, m_firstY,
                           m_secendValue, m_thridValue, m_fourValue, m_firstValue);
            }
        }
        if(m_thridY <= 0)
        {
            if(!m_pressFlag)
            {
                if(m_thridY  <= -height() / 3 / 2)
                {
                    m_firstY = height() / 3;
                    m_secendY = height() / 3 * 2;
                    m_thridY =  height();
                    m_fourY = 0;
                    m_thridValue = m_secendValue + 1;
                    if(m_thridValue > m_maxValue)
                    {
                        m_thridValue = 0;
                    }

                    painterNum(&painter, m_fourY, m_firstY, m_secendY, m_thridY,
                               m_fourValue, m_firstValue, m_secendValue, m_thridValue);
                }
                else
                {
                    m_firstY = height() / 3 * 2;
                    m_secendY = height();
                    m_thridY = 0;
                    m_fourY = height() / 3;

                    painterNum(&painter, m_thridY, m_fourY, m_firstY, m_secendY,
                               m_thridValue, m_fourValue, m_firstValue, m_secendValue);
                }
            }
            else
            {
                painterNum(&painter, m_thridY, m_fourY, m_firstY, m_secendY,
                           m_thridValue, m_fourValue, m_firstValue, m_secendValue);
            }
        }
        if(m_fourY <= 0)
        {
            if(!m_pressFlag)
            {
                if(m_fourY  <= -height() / 3 / 2)
                {
                    m_firstY = 0;
                    m_secendY = height() / 3;
                    m_thridY = height() / 3 * 2;
                    m_fourY = height();
                    m_fourValue = m_thridValue + 1;
                    if(m_fourValue > m_maxValue)
                    {
                        m_fourValue = 0;
                    }

                    painterNum(&painter, m_firstY, m_secendY, m_thridY, m_fourY,
                               m_firstValue, m_secendValue, m_thridValue, m_fourValue);
                }
                else
                {
                    m_firstY = height() / 3;
                    m_secendY = height() / 3 * 2;
                    m_thridY =  height();
                    m_fourY = 0;

                    painterNum(&painter, m_fourY, m_firstY, m_secendY, m_thridY,
                               m_fourValue, m_firstValue, m_secendValue, m_thridValue);
                }
            }
            else
            {
                painterNum(&painter, m_fourY, m_firstY, m_secendY, m_thridY,
                           m_fourValue, m_firstValue, m_secendValue, m_thridValue);
            }


        }
    }
    // 鼠标下划,Y轴值固定每次移动加2,然后在判读每一个处于显示区域外(Y坐标为0)的矩形Y坐标是否
    // 小于0,当小于零时处于最上方显示区域外的第4个矩形显示区域开始向下移动,以此形成循环滚动的视
    // 觉效果
    else 
    {
        if(m_fourY <= 0)
        {
            if(!m_pressFlag)
            {
                if(m_fourY  >= -height() / 3 / 2)
                {
                    m_firstY = height() / 3;
                    m_secendY = height() / 3 * 2;
                    m_thridY = -height() / 3;
                    m_fourY = 0;
                    m_thridValue = m_fourValue - 1;
                    if(m_thridValue < 0)
                    {
                        m_thridValue = m_maxValue;
                    }

                    painterNum(&painter, m_fourY, m_firstY, m_secendY, m_thridY,
                               m_fourValue, m_firstValue, m_secendValue, m_thridValue);
                }
                else
                {
                    m_firstY = 0;
                    m_secendY = height() / 3;
                    m_thridY = height() / 3 * 2;
                    m_fourY = -height() / 3;

                    painterNum(&painter, m_firstY, m_secendY, m_thridY, m_fourY,
                               m_firstValue, m_secendValue, m_thridValue, m_fourValue);
                }
            }
            else
            {
                painterNum(&painter, m_firstY, m_secendY, m_thridY, m_fourY,
                           m_firstValue, m_secendValue, m_thridValue, m_fourValue);
            }
        }
        if(m_thridY <= 0)
        {
            if(!m_pressFlag)
            {
                if(m_thridY  >= -height() / 3 / 2)
                {
                    m_firstY = height() / 3 * 2;
                    m_secendY = -height() / 3;
                    m_thridY = 0;
                    m_fourY = height() / 3;
                    m_secendValue = m_thridValue - 1;
                    if(m_secendValue < 0)
                    {
                        m_secendValue = m_maxValue;
                    }

                    painterNum(&painter, m_thridY, m_fourY, m_firstY, m_secendY,
                               m_thridValue, m_fourValue, m_firstValue, m_secendValue);
                }
                else
                {
                    m_firstY = height() / 3;
                    m_secendY = height() / 3 * 2;
                    m_thridY = -height() / 3;
                    m_fourY = 0;
                    if(m_thridValue < 0)
                    {
                        m_thridValue = m_maxValue;
                    }

                    painterNum(&painter, m_fourY, m_firstY, m_secendY, m_thridY,
                               m_fourValue, m_firstValue, m_secendValue, m_thridValue);
                }
            }
            else
            {
                painterNum(&painter, m_fourY, m_firstY, m_secendY, m_thridY,
                           m_fourValue, m_firstValue, m_secendValue, m_thridValue);
            }
        }
        if(m_secendY <= 0)
        {
            if(!m_pressFlag)
            {
                if(m_secendY  >= -height() / 3 / 2)
                {
                    m_firstY = -height() / 3;
                    m_secendY = 0;
                    m_thridY = height() / 3;
                    m_fourY = height() / 3 * 2;
                    m_firstValue = m_secendValue - 1;
                    if(m_firstValue < 0)
                    {
                        m_firstValue = m_maxValue;
                    }

                    painterNum(&painter, m_secendY, m_thridY, m_fourY, m_firstY,
                               m_secendValue, m_thridValue, m_fourValue, m_firstValue);
                }
                else
                {
                    m_firstY = height() / 3 * 2;
                    m_secendY = -height() / 3;
                    m_thridY = 0;
                    m_fourY = height() / 3;

                    painterNum(&painter, m_thridY, m_fourY, m_firstY, m_secendY,
                               m_thridValue, m_fourValue, m_firstValue, m_secendValue);
                }
            }
            else
            {
                painterNum(&painter, m_thridY, m_fourY, m_firstY, m_secendY,
                           m_thridValue, m_fourValue, m_firstValue, m_secendValue);
            }
        }
        if(m_firstY <= 0)
        {
            if(!m_pressFlag)
            {
                if(m_firstY  >= -height() / 3 / 2)
                {
                    m_firstY = 0;
                    m_secendY = height() / 3;
                    m_thridY = height() / 3 * 2;
                    m_fourY = -height() / 3;
                    m_fourValue = m_firstValue - 1;
                    if(m_fourValue < 0)
                    {
                        m_fourValue = m_maxValue;
                    }

                    painterNum(&painter, m_firstY, m_secendY, m_thridY, m_fourY,
                               m_firstValue, m_secendValue, m_thridValue, m_fourValue);
                }
                else
                {
                    m_firstY = -height() / 3;
                    m_secendY = 0;
                    m_thridY = height() / 3;
                    m_fourY = height() / 3 * 2;

                    painterNum(&painter, m_secendY, m_thridY, m_fourY, m_firstY,
                               m_secendValue, m_thridValue, m_fourValue, m_firstValue);
                }
            }
            else
            {
                painterNum(&painter, m_secendY, m_thridY, m_fourY, m_firstY,
                           m_secendValue, m_thridValue, m_fourValue, m_firstValue);
            }
        }
    }

    // 绘制临界线
    painter.save();
    QPen pen(Qt::blue);
    pen.setWidth(2);
    painter.setPen(pen);
    painter.drawLine(0, height() / 3, width(), height() / 3);
    painter.drawLine(0, height() / 3 * 2, width(), height() / 3 * 2);
    painter.restore();

}

// 绘制数字显示区域,同时循环滚动绘制数字
void TimeSelectWidget::painterNum(QPainter *pPainter, int y1, int y2, int y3, int y4, int value1, int value2, int value3, int value4)
{
    pPainter->save();
    QPen txetPen(Qt::white);
    txetPen.setWidth(2);
    pPainter->setPen(txetPen);
    QFont font = pPainter->font();
    font.setBold(true);

    font.setPixelSize(18);
    pPainter->setFont(font);
    QRect rect(0, y1, width(), height() / 3);
    pPainter->drawText(rect, Qt::AlignCenter, QString::number(value1));

    font.setPixelSize(24);
    pPainter->setFont(font);
    rect = QRect(0, y2, width(), height() / 3);
    pPainter->drawText(rect, Qt::AlignCenter, QString::number(value2));

    font.setPixelSize(18);
    pPainter->setFont(font);
    rect = QRect(0, y3, width(), height() / 3);
    pPainter->drawText(rect, Qt::AlignCenter, QString::number(value3));

    font.setPixelSize(18);
    pPainter->setFont(font);
    rect = QRect(0, y4, width(), height() / 3);
    pPainter->drawText(rect, Qt::AlignCenter, QString::number(value4));
    pPainter->restore();

    m_selectValue = value2;
}



第三步重载鼠标事件:

// 获取鼠标按下的开始位置
void TimeSelectWidget::mousePressEvent(QMouseEvent *event)
{
    m_startPos = event->pos();
    m_pressFlag = true;
}

void TimeSelectWidget::mouseMoveEvent(QMouseEvent *event)
{
    // 鼠标按下才开始进行移动(暂时没有限定鼠标按键)
    if(m_pressFlag)
    {
        // 小于0则说明鼠标是上划,大于0则是下划,然后根据鼠标移动后Y坐标的临界值去改变rect区域
        // 显示的数字
        if(event->pos().y() - m_startPos.y() < 0)
        {
            if(m_firstY == -height() / 3)
            {
                m_firstY = height();
                m_firstValue = m_fourValue + 1;
                if(m_firstValue > m_maxValue)
                {
                    m_firstValue = 0;
                }
            }
            if(m_secendY == -height() / 3)
            {
                m_secendY = height();
                m_secendValue = m_firstValue + 1;
                if(m_secendValue > m_maxValue)
                {
                    m_secendValue = 0;
                }
            }
            if(m_thridY == -height() / 3)
            {
                m_thridY = height();
                m_thridValue = m_secendValue + 1;
                if(m_thridValue > m_maxValue)
                {
                    m_thridValue = 0;
                }
            }
            if(m_fourY == -height() / 3)
            {
                m_fourY = height();
                m_fourValue = m_thridValue + 1;
                if(m_fourValue > m_maxValue)
                {
                    m_fourValue = 0;
                }
            }
            m_firstY -= m_moveValue;
            m_secendY -= m_moveValue;
            m_thridY -= m_moveValue;
            m_fourY -= m_moveValue;
            m_curValueFlag = false;
        }
        else
        {
            if(m_firstY == 0)
            {
                m_fourY = -height() / 3;
                m_fourValue = m_firstValue - 1;
                if(m_fourValue < 0)
                {
                    m_fourValue = m_maxValue;
                }
            }
            if(m_fourY == 0)
            {
                m_thridY = -height() / 3;
                m_thridValue = m_fourValue - 1;
                if(m_thridValue < 0)
                {
                    m_thridValue = m_maxValue;
                }
            }
            if(m_thridY == 0)
            {
                m_secendY = -height() / 3;
                m_secendValue = m_thridValue - 1;
                if(m_secendValue < 0)
                {
                    m_secendValue = m_maxValue;
                }
            }
            if(m_secendY == 0)
            {
                m_firstY = -height() / 3;
                m_firstValue = m_secendValue - 1;
                if(m_firstValue < 0)
                {
                    m_firstValue = m_maxValue;
                }
            }
            m_firstY += m_moveValue;
            m_secendY += m_moveValue;
            m_thridY += m_moveValue;
            m_fourY += m_moveValue;
            m_curValueFlag = true;
        }

        update();
    }
}

void TimeSelectWidget::mouseReleaseEvent(QMouseEvent *event)
{
    m_pressFlag = false;
    update();
}

功能较为简单就不做过多的文字说明了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值