zoukankan      html  css  js  c++  java
  • Qt添加自定义控件

    由于在自带的控件中没有发现滚动选择时间的控件,所以参考网上别人写的控件做了一点修改。

    先看效果:

    上代码:

    TimeScroll.h

    QT_BEGIN_NAMESPACE
    namespace Ui { class TimeScroll; }
    QT_END_NAMESPACE
    
    class TimeScroll : public QWidget
    {
        Q_OBJECT
        Q_PROPERTY(int deviation READ readDeviation WRITE setDeviation )
    
    public:
        TimeScroll(QWidget *parent = nullptr);
        ~TimeScroll();
    
        void setRange(double min, double max);
        void setCurrentValue(double value);
            //获取当前值
        double readValue();
    
    protected:
        void mousePressEvent(QMouseEvent *);
    
        void mouseMoveEvent(QMouseEvent *);
    
        void mouseReleaseEvent(QMouseEvent *);
    
        void wheelEvent(QWheelEvent *);
    
        void paintEvent(QPaintEvent *);
        //描绘数字
        void paintNum(QPainter &painter, double num, int deviation,bool isMiddle= false);
        //使选中的数字回到屏幕中间
        void homing();
        //鼠标移动偏移量,默认为0
        int readDeviation();
        //设置偏移量
        void setDeviation(int n);
    
    signals:
    
        void currentValueChanged(double value);
    
        void deviationChange(double deviation);
    
    
    private:
        double m_minRange;      //最小值
        double m_maxRange;      //最大值
        double m_currentValue;  //当前选中的值
        bool isDragging;        //鼠标是否按下
        int m_deviation;        //偏移量,记录鼠标按下后移动的垂直距离
        int m_mouseSrcPos;
        int m_numSize;
        QPropertyAnimation *homingAni;
        const double interval;  //间隔大小
        const int devide;       //分隔数量
    
        Ui::TimeScroll *ui;
    };

    TimeScroll.cpp

    TimeScroll::TimeScroll(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::TimeScroll),
        m_minRange(0),      //最小值默认为0
        m_maxRange(59),    //最大值默认100
        m_currentValue(0), //当前值默认50
        isDragging(false),
        m_deviation(0),     //默认偏移量为0
        m_numSize(12),
        interval(1),      //间隔默认0.5
        devide(7)           //默认分成7格
    {
    
        ui->setupUi(this);
    
        homingAni = new QPropertyAnimation(this, "deviation");
        homingAni->setDuration(300);
        homingAni->setEasingCurve(QEasingCurve::OutQuad);
    }
    
    TimeScroll::~TimeScroll()
    {
        delete ui;
    }
    /*
     * 设置范围
     * double min 最小值
     * double max 最大值
    */
    void TimeScroll::setRange(double min, double max)
    {
        m_minRange = min;
        m_maxRange = max;
        if (m_currentValue < min)
        {
            m_currentValue = min;
        }
        if (m_currentValue > max)
        {
            m_currentValue = max;
        }
        repaint();
    }
    /*
     * 设置当前值
     *  double value 传入的当前值
     */
    void TimeScroll::setCurrentValue(double value) {
        if(value < m_minRange){
            m_currentValue = m_minRange;
        }
        if(value > m_maxRange){
            m_currentValue = m_maxRange;
        }
        repaint();
    }
    //获取当前值
    double TimeScroll::readValue()
    {
        if(m_currentValue < m_minRange){
            return m_maxRange - (m_minRange-m_currentValue) + 1;
        }
        if(m_currentValue > m_maxRange){
            return m_minRange + (m_currentValue - m_maxRange) - 1;
        }
        return m_currentValue;
    }
    
    void TimeScroll::mousePressEvent(QMouseEvent *e)
    {
        qDebug()<<"mouse pressed on vertical scroll";
    
        homingAni->stop();
        isDragging = true;
        m_mouseSrcPos = e->pos().y();
        QWidget::mousePressEvent(e);
    }
    
    void TimeScroll::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;
    //        }
    //        if ((m_currentValue < m_minRange - (devide * interval)&& e->pos().y() >= m_mouseSrcPos)){
    //                m_currentValue = (int)qAbs(m_currentValue)%(int)(m_maxRange + 1);
    //        }
    //        if(m_currentValue > m_maxRange + (devide * interval) && e->pos().y() <= m_mouseSrcPos){
    //                m_currentValue = (int)m_currentValue%(int)(m_maxRange + 1);
    //        }
            m_deviation = e->pos().y() - m_mouseSrcPos;
            //若移动速度过快,则进行限制
            if (m_deviation > (height() - 1) / devide)
            {
                m_deviation = (height() - 1) / devide;
            }
            else if (m_deviation < -(height() - 1) / devide)
            {
                m_deviation = -( height() - 1) / devide;
            }
            qInfo()<<m_deviation;
    
            emit deviationChange((double)m_deviation / ((height() - 1) / devide));
            repaint();
        }
    }
    
    void TimeScroll::mouseReleaseEvent(QMouseEvent *)
    {
        if (isDragging)
        {
            isDragging = false;
            homing();
        }
    }
    
    void TimeScroll::wheelEvent(QWheelEvent *e)
    {
        if (e->delta() > 0)
        {
            m_deviation = (this->height() - 1) / devide;
        }
        else
        {
            m_deviation = -(this->height() - 1) / devide;
        }
        homing();
        repaint();
    }
    
    void TimeScroll::paintEvent(QPaintEvent *e)
    {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing, true);
        int Height = height() - 1;
    
        if ( m_deviation >= Height / devide && m_currentValue > (m_minRange - devide * interval ))
        {
            m_mouseSrcPos += Height / devide;
            m_deviation -= Height / devide;
            m_currentValue -= interval;
        }
    
        if ( m_deviation <= -Height / devide && m_currentValue < (m_maxRange + devide * interval))
        {
            m_mouseSrcPos -= Height / devide;
            m_deviation += Height / devide;
            m_currentValue += interval;
        }
        qInfo()<< "paint:"<<m_deviation;
        //middle number
        if(m_currentValue < (m_minRange + devide/2)){
            // 中间值
            if(m_currentValue >= m_minRange){
                paintNum(painter,m_currentValue,m_deviation,true);
                for(int i = 1; i <= devide/2; ++i){
                    paintNum(painter,m_currentValue + i,m_deviation + Height / devide*i);
                    if(m_currentValue - i - m_minRange< 0){
                        paintNum(painter,m_maxRange + (m_currentValue  -  i) + 1 - m_minRange,m_deviation - Height / devide*i);
                    }else{
                        paintNum(painter,m_currentValue - i,m_deviation - Height / devide*i);
                    }
                }
            }else{
                paintNum(painter,m_maxRange - (m_minRange - m_currentValue) + 1,m_deviation,true);
                for(int i = 1; i <= devide/2; ++i){
                    paintNum(painter,m_maxRange - (m_minRange - m_currentValue) + 1 - i,m_deviation - Height / devide*i);
                    if(( m_currentValue - m_minRange) + 1 + i > 0){
                        paintNum(painter,m_minRange + ( m_currentValue - m_minRange)  + i,m_deviation + Height / devide*i);
                    }else{
                        paintNum(painter,m_maxRange - (m_minRange - m_currentValue) + 1 + i,m_deviation + Height / devide *i);
                    }
                }
                if(m_currentValue == m_minRange - devide/2 -1){
                    m_currentValue = m_maxRange - devide/2;
                }
            }
    
        }else if(m_currentValue > m_maxRange - devide/2){
            if(m_currentValue <= m_maxRange){
                paintNum(painter,m_currentValue,m_deviation,true);
                for(int i = 1; i <= devide/2; ++i){
                    paintNum(painter,m_currentValue - i,m_deviation - Height / devide *i);
                    if(m_currentValue + i > m_maxRange){
                        paintNum(painter,     m_minRange + m_currentValue -m_maxRange +i -1,m_deviation + Height / devide *i);
                    }else{
                        paintNum(painter,m_currentValue +i,m_deviation + Height / devide*i);
                    }
                }
            }else{
                paintNum(painter,m_minRange + (m_currentValue - m_maxRange) - 1,m_deviation,true);
                for(int i = 1; i <= devide/2; ++i){
                    paintNum(painter,m_minRange + (m_currentValue - m_maxRange) + i - 1,m_deviation + Height / devide *i);
                    if( (m_currentValue - m_maxRange) - 1- i < 0){
                        paintNum(painter,  m_currentValue - i,m_deviation - Height / devide *i);
                    }else{
                        paintNum(painter,m_minRange + (m_currentValue - m_maxRange) -i - 1,m_deviation - Height / devide * i);
                    }
                }
                if(m_currentValue == m_maxRange + devide/2 + 1){
                    m_currentValue = m_minRange + devide/2;
                }
            }
        }else{
            paintNum(painter,m_currentValue,m_deviation,true);
            for(int i = 1; i <= devide/2; ++i){
                paintNum(painter,m_currentValue- interval *i,m_deviation - Height / devide *i);
                paintNum(painter,m_currentValue+ interval *i,m_deviation + Height / devide *i);
            }
        }
    
    }
    /*
     * 根据偏移量描绘数字
     * double num 需要显示的数字
     * int deviation 数字相对中间的偏移量
    */
    void TimeScroll::paintNum(QPainter &painter, double num, int deviation,bool isMiddle)
    {
        int Width = width() - 1;
        int Height = height() - 1;
        int size = (Height - qAbs(deviation)) / m_numSize; //偏移量越大,数字越小
        int transparency = 255 - 255 * qAbs(deviation) / Height;
        int height = Height / devide;
        int y = Height / 2 + deviation - height / 2;
    
        QFont font;
        font.setPixelSize(size);
        painter.setFont(font);
        painter.setPen(QColor(255, 2,2,transparency));
    
        if ( y >= 0 && y + height < Height)
        {
            // 中间值画框
            if(isMiddle) {
                painter.drawRect(0, y, Width, height);
            }
            painter.drawText(QRectF(0, y, Width-20, height),
                             Qt::AlignCenter,
                             QString::number(num, 'f', 1));
        }
    }
    
    /*
     * 使选中的数字回到屏幕中间
    */
    void TimeScroll::homing()
    {
        if ( m_deviation > height() / 10)
        {
            homingAni->setStartValue( ( height() - 1 ) / 8 - m_deviation);
            homingAni->setEndValue(0);
            m_currentValue -= interval;
        }
        else if ( m_deviation > -height() / 10 )
        {
            homingAni->setStartValue(m_deviation);
            homingAni->setEndValue(0);
        }
        else if ( m_deviation < -height() / 10 )
        {
            homingAni->setStartValue(-(height() - 1) / 8 - m_deviation);
            homingAni->setEndValue(0);
            m_currentValue += interval;
        }
    
        emit currentValueChanged(m_currentValue);
        homingAni->start();
    }
    
    int TimeScroll::readDeviation()
    {
        return m_deviation;
    }
    
    void TimeScroll::setDeviation(int n)
    {
        m_deviation = n;
        repaint();
    }
  • 相关阅读:
    Codeforces467C George and Job
    Codeforces205E Little Elephant and Furik and RubikLittle Elephant and Furik and Rubik
    Codeforce205C Little Elephant and Interval
    51nod1829 函数
    51nod1574 排列转换
    nowcoder35B 小AA的数列
    Codeforce893E Counting Arrays
    gym101612 Consonant Fencity
    CodeForces559C Gerald and Giant Chess
    CodeForces456D A Lot of Games
  • 原文地址:https://www.cnblogs.com/ohsolong/p/14153404.html
Copyright © 2011-2022 走看看