QT 实现Android 风格的开关控件

发布时间:2019-07-15

概述

本例子是举例如何使用QT实现Android风格的开关控件

详细

本例子是举例如何使用QT实现Android风格的开关控件,可以使用画颜色的方式,也可使用画图片方式。


一、运行效果

result.gif

这是画颜色的方式,画图片的方式的运行效果这里不再展示


二、实现过程

要实现开关控件,我们需要按以下步骤进行实现

1. 数据定义

    QColor m_onColor;   //开状态的颜色
    QColor m_offColor;  //关状态的颜色
    bool m_Value;   //开关值
    int m_timerID;  //移动定时器id
    int m_offset;   //移动过程中圆心的x坐标
    bool m_isMove;
    QPoint m_pressPos;  //鼠标按下的位置
    bool m_DisableVal;
    QPixmap m_BkgPixmapNormal;  //使用图片方式时保存开状态背景
    QPixmap m_BkgPixmapPress;   //使用图片方式时保存关状态背景
    QPixmap m_ChunkPixmapNormal;    //使用图片方式时保存开状态滑块
    QPixmap m_ChunkPixmapPress;//使用图片方式时保存关状态滑块


2. 鼠标事件处理,这里只写出鼠标释放部分的代码

        if (m_isMove)
        {
            m_isMove = false;
            m_offset = 0;
            int xMove = event->pos().x()-m_pressPos.x();
            if (abs(xMove) >= (this->rect().width()-this->rect().height())/2)
            {
                if (m_reverse)
                {
                    if (xMove > 0 && m_Value)
                    {
                        setOnoffStatus(!m_Value);
                        emit valueChanged( m_Value);
                    }
                    else if (!m_Value)
                    {
                        setOnoffStatus(!m_Value);
                        emit valueChanged( m_Value);
                    }
                    else
                    {
                        update();
                    }
                }
                else
                {
                    if (xMove < 0 && m_Value)
                    {
                        setOnoffStatus(!m_Value);
                        emit valueChanged( m_Value);
                    }
                    else if (!m_Value)
                    {
                        setOnoffStatus(!m_Value);
                        emit valueChanged( m_Value);
                    }
                    else
                    {
                        update();
                    }
                }
            }
            else
            {
                update();
            }
        }
        else
        {
            changeStatus(!m_Value);
        }


3. 动画过渡过程处理

        if (m_reverse)
        {
            if (m_Value)
            {
                m_offset -= 8;
            }
            else
            {
                m_offset += 8;
            }
        }
        else
        {
            if (m_Value)
            {
                m_offset += 8;
            }
            else
            {
                m_offset -= 8;
            }
        }

        if ((m_offset <= this->rect().height()/2) || (m_offset >= (this->rect().width()-this->rect().height()/2)))
        {
            killTimer(m_timerID);
            m_timerID = 0;
            m_offset = 0;
        }
        update();


4. 根据各数据的值画出画面效果, 这里只展示部分代码

            //画关闭色
            QPainterPath path;
            QRectF mrect = QRect(rc.x()+1, rc.top()+margin+1, m_offset-1, margin*4);
            path.moveTo(mrect.topRight() - QPointF(radius, 0));
            path.lineTo(mrect.topLeft() + QPointF(radius, 0));
            path.quadTo(mrect.topLeft(), mrect.topLeft() + QPointF(0, radius));
            path.lineTo(mrect.bottomLeft() + QPointF(0, -radius));
            path.quadTo(mrect.bottomLeft(), mrect.bottomLeft() + QPointF(radius, 0));
            path.lineTo(mrect.bottomRight() - QPointF(radius, 0));
            path.quadTo(mrect.bottomRight(), mrect.bottomRight() + QPointF(0, -radius));
            path.lineTo(mrect.topRight() + QPointF(0, radius));
            path.quadTo(mrect.topRight(), mrect.topRight() + QPointF(-radius, -0));
            painter.setPen(QPen(QColor(70, 70, 70)));
            painter.setBrush(QBrush(QColor(m_onColor.red()*2/3, m_onColor.green()*2/3, m_onColor.blue()*2/3)));
            painter.fillPath(path, m_onColor);
            painter.drawPath(path);

            //画打开色
            QPainterPath path2;
            mrect = QRect(m_offset, rc.top()+margin+1, rc.width()-m_offset-1, margin*4);
            path2.moveTo(mrect.topRight() - QPointF(radius, 0));
            path2.lineTo(mrect.topLeft() + QPointF(radius, 0));
            path2.quadTo(mrect.topLeft(), mrect.topLeft() + QPointF(0, radius));
            path2.lineTo(mrect.bottomLeft() + QPointF(0, -radius));
            path2.quadTo(mrect.bottomLeft(), mrect.bottomLeft() + QPointF(radius, 0));
            path2.lineTo(mrect.bottomRight() - QPointF(radius, 0));
            path2.quadTo(mrect.bottomRight(), mrect.bottomRight() + QPointF(0, -radius));
            path2.lineTo(mrect.topRight() + QPointF(0, radius));
            path2.quadTo(mrect.topRight(), mrect.topRight() + QPointF(-radius, -0));
            painter.setPen(QPen(QColor(70, 70, 70)));
            painter.setBrush(QBrush(QColor(m_offColor.red()*2/3, m_offColor.green()*2/3, m_offColor.blue()*2/3)));
            painter.fillPath(path2, m_offColor);
            painter.drawPath(path2);

            //画圆圈
            if (m_offset > rc.width()/2)
            {
                painter.setPen(QPen(QColor(70, 70, 70)));
                painter.setBrush(QBrush(m_onColor));
                painter.drawEllipse(rc.x()+m_offset-rc.height()/2, rc.top(), rc.height(), rc.height());
            }
            else
            {
                painter.setPen(QPen(QColor(70, 70, 70)));
                painter.setBrush(QBrush(m_offColor));
                painter.drawEllipse(rc.x()+m_offset-rc.height()/2, rc.top(), rc.height(), rc.height());
            }


三、项目结构图

image.png


四、控件使用介绍

控件创建后可以使用以下两个函数改变控件开关状态的颜色

    /*set text on color*/
    const QColor onColor() const;
    void setOnColor(const QColor &data);

    /*set text off color*/
    const QColor offColor() const;
    void setOffColor(const QColor &data);


如果要使用画图片的方式,可使用以下函数设置图片

    void setNormalBkgPix(const QPixmap &pix);//开状态背景
    void setPressBkgPix(const QPixmap &pix);    //关状态背景
    void setNormalChunkPix(const QPixmap &pix); //开状态滑块
    void setPressChunkPix(const QPixmap &pix);  //关状态滑块



本实例支付的费用只是购买源码的费用,如有疑问欢迎在文末留言交流,如需作者在线代码指导、定制等,在作者开启付费服务后,可以点击“购买服务”进行实时联系,请知悉,谢谢
手机上随时阅读、收藏该文章 ?请扫下方二维码