• 【Qt炫酷动画】1.easing官方demo详细剖析



    1.demo效果

    在这里插入图片描述

    2.demo项目构建

    • 打开Qt Creator,按照图上操作
      在这里插入图片描述
    • 使用Minggw64构建运行
      在这里插入图片描述

    3.代码详细剖析

    代码目录结构

     ├📁easing
     |  📄animation.h
     |  📦​easing.pro
     |  🎴​easing.qrc
     |  🎴​form.ui
     |  📄main.cpp
     |  📄window.cpp
     |  📄window.h
      ├📁images
      |  🎴​qt-logo.png

    代码实现

    • /easing/animation.h
    #ifndef ANIMATION_H
    #define ANIMATION_H
    
    #include 
    
    #include 
    
    class Animation : public QPropertyAnimation {
    public:
        enum PathType {
            LinearPath,
            CirclePath,
            NPathTypes
        };
        Animation(QObject *target, const QByteArray &prop)
            : QPropertyAnimation(target, prop)
        {
            setPathType(LinearPath);
        }
    
        //设置路径直线、圆
        void setPathType(PathType pathType)
        {
            if (pathType >= NPathTypes)
                qWarning("Unknown pathType %d", pathType);
    
            m_pathType = pathType;
            m_path = QPainterPath();
        }
    
        //每一毫秒都会调用的函数,实现这个虚函数
        void updateCurrentTime(int currentTime) override
        {
            if (m_pathType == CirclePath) {
                //圆
                if (m_path.isEmpty()) {
                    //计算开始点和结束点
                    QPointF to = endValue().toPointF();
                    QPointF from = startValue().toPointF();
                    //移动到开始点
                    m_path.moveTo(from);
                    //添加路径
                    m_path.addEllipse(QRectF(from, to));
                }
                //总时长
                int dura = duration();
    
                //当前进度
                const qreal progress = ((dura == 0) ? 1 : ((((currentTime - 1) % dura) + 1) / qreal(dura)));
                //根据进度计算
                qreal easedProgress = easingCurve().valueForProgress(progress);
                if (easedProgress > 1.0) {
                    easedProgress -= 1.0;
                } else if (easedProgress < 0) {
                    easedProgress += 1.0;
                }
                //计算位置
                QPointF pt = m_path.pointAtPercent(easedProgress);
                //更新值并发送信号
                updateCurrentValue(pt);
                emit valueChanged(pt);
            } else {
                QPropertyAnimation::updateCurrentTime(currentTime);
            }
        }
    
        QPainterPath m_path;
        PathType m_pathType;
    };
    
    #endif // ANIMATION_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • /easing/easing.pro
    QT += widgets
    requires(qtConfig(listwidget))
    
    HEADERS = window.h \
              animation.h
    SOURCES = main.cpp \
              window.cpp
    
    FORMS   = form.ui
    
    RESOURCES = easing.qrc
    
    # install
    target.path = $$[QT_INSTALL_EXAMPLES]/widgets/animation/easing
    INSTALLS += target
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • /easing/form.ui
    <?xml version="1.0" encoding="UTF-8"?>
    <ui version="4.0">
     <class>Form</class>
     <widget class="QWidget" name="Form">
      <property name="geometry">
       <rect>
        <x>0</x>
        <y>0</y>
        <width>545</width>
        <height>471</height>
       </rect>
      </property>
      <property name="windowTitle">
       <string>Easing curves</string>
      </property>
      <layout class="QGridLayout" name="gridLayout">
       <item row="0" column="0" colspan="2">
        <widget class="QListWidget" name="easingCurvePicker">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
         <property name="maximumSize">
          <size>
           <width>16777215</width>
           <height>120</height>
          </size>
         </property>
         <property name="verticalScrollBarPolicy">
          <enum>Qt::ScrollBarAlwaysOff</enum>
         </property>
         <property name="movement">
          <enum>QListView::Static</enum>
         </property>
         <property name="isWrapping" stdset="0">
          <bool>false</bool>
         </property>
         <property name="viewMode">
          <enum>QListView::IconMode</enum>
         </property>
         <property name="selectionRectVisible">
          <bool>false</bool>
         </property>
        </widget>
       </item>
       <item row="1" column="0">
        <layout class="QVBoxLayout" name="verticalLayout">
         <item>
          <widget class="QGroupBox" name="groupBox_2">
           <property name="maximumSize">
            <size>
             <width>16777215</width>
             <height>16777215</height>
            </size>
           </property>
           <property name="title">
            <string>Path type</string>
           </property>
           <layout class="QGridLayout" name="gridLayout_2">
            <item row="0" column="0">
             <widget class="QRadioButton" name="lineRadio">
              <property name="maximumSize">
               <size>
                <width>16777215</width>
                <height>40</height>
               </size>
              </property>
              <property name="layoutDirection">
               <enum>Qt::LeftToRight</enum>
              </property>
              <property name="text">
               <string>Line</string>
              </property>
              <property name="checked">
               <bool>true</bool>
              </property>
              <attribute name="buttonGroup">
               <string>buttonGroup</string>
              </attribute>
             </widget>
            </item>
            <item row="1" column="0">
             <widget class="QRadioButton" name="circleRadio">
              <property name="maximumSize">
               <size>
                <width>16777215</width>
                <height>40</height>
               </size>
              </property>
              <property name="text">
               <string>Circle</string>
              </property>
              <attribute name="buttonGroup">
               <string>buttonGroup</string>
              </attribute>
             </widget>
            </item>
           </layout>
          </widget>
         </item>
         <item>
          <widget class="QGroupBox" name="groupBox">
           <property name="sizePolicy">
            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
             <horstretch>0</horstretch>
             <verstretch>0</verstretch>
            </sizepolicy>
           </property>
           <property name="title">
            <string>Properties</string>
           </property>
           <layout class="QFormLayout" name="formLayout">
            <property name="fieldGrowthPolicy">
             <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
            </property>
            <item row="0" column="0">
             <widget class="QLabel" name="label">
              <property name="sizePolicy">
               <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="minimumSize">
               <size>
                <width>0</width>
                <height>30</height>
               </size>
              </property>
              <property name="text">
               <string>Period</string>
              </property>
             </widget>
            </item>
            <item row="0" column="1">
             <widget class="QDoubleSpinBox" name="periodSpinBox">
              <property name="enabled">
               <bool>false</bool>
              </property>
              <property name="sizePolicy">
               <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
                <horstretch>0</horstretch>
                <verstretch>0</verstretch>
               </sizepolicy>
              </property>
              <property name="minimumSize">
               <size>
                <width>0</width>
                <height>30</height>
               </size>
              </property>
              <property name="minimum">
               <double>-1.000000000000000</double>
              </property>
              <property name="singleStep">
               <double>0.100000000000000</double>
              </property>
              <property name="value">
               <double>-1.000000000000000</double>
              </property>
             </widget>
            </item>
            <item row="2" column="1">
             <widget class="QDoubleSpinBox" name="amplitudeSpinBox">
              <property name="enabled">
               <bool>false</bool>
              </property>
              <property name="minimumSize">
               <size>
                <width>0</width>
                <height>30</height>
               </size>
              </property>
              <property name="minimum">
               <double>-1.000000000000000</double>
              </property>
              <property name="singleStep">
               <double>0.100000000000000</double>
              </property>
              <property name="value">
               <double>-1.000000000000000</double>
              </property>
             </widget>
            </item>
            <item row="4" column="0">
             <widget class="QLabel" name="label_3">
              <property name="minimumSize">
               <size>
                <width>0</width>
                <height>30</height>
               </size>
              </property>
              <property name="text">
               <string>Overshoot</string>
              </property>
             </widget>
            </item>
            <item row="4" column="1">
             <widget class="QDoubleSpinBox" name="overshootSpinBox">
              <property name="enabled">
               <bool>false</bool>
              </property>
              <property name="minimumSize">
               <size>
                <width>0</width>
                <height>30</height>
               </size>
              </property>
              <property name="minimum">
               <double>-1.000000000000000</double>
              </property>
              <property name="singleStep">
               <double>0.100000000000000</double>
              </property>
              <property name="value">
               <double>-1.000000000000000</double>
              </property>
             </widget>
            </item>
            <item row="2" column="0">
             <widget class="QLabel" name="label_2">
              <property name="minimumSize">
               <size>
                <width>0</width>
                <height>30</height>
               </size>
              </property>
              <property name="text">
               <string>Amplitude</string>
              </property>
             </widget>
            </item>
           </layout>
          </widget>
         </item>
         <item>
          <spacer name="verticalSpacer">
           <property name="orientation">
            <enum>Qt::Vertical</enum>
           </property>
           <property name="sizeHint" stdset="0">
            <size>
             <width>20</width>
             <height>40</height>
            </size>
           </property>
          </spacer>
         </item>
        </layout>
       </item>
       <item row="1" column="1">
        <widget class="QGraphicsView" name="graphicsView">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
        </widget>
       </item>
      </layout>
     </widget>
     <resources/>
     <connections/>
     <buttongroups>
      <buttongroup name="buttonGroup"/>
     </buttongroups>
    </ui>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • /easing/main.cpp
    #include 
    #include "window.h"
    #include 
    int main(int argc, char **argv)
    {
        Q_INIT_RESOURCE(easing);
        QApplication app(argc, argv);
        Window w;
    
        //固定400*400大小
        w.resize(400, 400);
        w.show();
    
        return app.exec();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • /easing/window.cpp
    #include "window.h"
    
    Window::Window(QWidget *parent)
        : QWidget(parent),
        m_iconSize(64, 64)
    {
        m_ui.setupUi(this);
    
    
        //listview设置图标显示模式
        m_ui.easingCurvePicker->setIconSize(m_iconSize);
        //设置最小高度
        m_ui.easingCurvePicker->setMinimumHeight(m_iconSize.height() + 50);
    
        //直线或圆设置按钮组
        m_ui.buttonGroup->setId(m_ui.lineRadio, 0);
        m_ui.buttonGroup->setId(m_ui.circleRadio, 1);
    
    
        //曲线对象
        QEasingCurve dummy;
    
        //周期
        m_ui.periodSpinBox->setValue(dummy.period());
        //振幅
        m_ui.amplitudeSpinBox->setValue(dummy.amplitude());
        //过冲
        m_ui.overshootSpinBox->setValue(dummy.overshoot());
    
        //list中被点击绑定
        connect(m_ui.easingCurvePicker, &QListWidget::currentRowChanged,
                this, &Window::curveChanged);
    
        //按钮组被点击
        connect(m_ui.buttonGroup, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked),
                this, &Window::pathChanged);
    
        connect(m_ui.periodSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
                this, &Window::periodChanged);
        connect(m_ui.amplitudeSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
                this, &Window::amplitudeChanged);
        connect(m_ui.overshootSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged),
                this, &Window::overshootChanged);
    
        //初始化List及图标
        createCurveIcons();
    
    
        //声明图片
        QPixmap pix(QLatin1String(":/images/qt-logo.png"));
    
        //item对象
        m_item = new PixmapItem(pix);
        //场景添加对象
        m_scene.addItem(m_item);
        m_ui.graphicsView->setScene(&m_scene);
    
        //声明动画对象,赋值动画对象和 位置属性
        m_anim = new Animation(m_item, "pos");
        //设置动画曲线
        m_anim->setEasingCurve(QEasingCurve::OutBounce);
    
        //list默认选中第一个
        m_ui.easingCurvePicker->setCurrentRow(int(QEasingCurve::OutBounce));
    
        startAnimation();
    }
    
    QEasingCurve createEasingCurve(QEasingCurve::Type curveType)
    {
        QEasingCurve curve(curveType);
    
        if (curveType == QEasingCurve::BezierSpline) {
            //贝塞尔曲线
            curve.addCubicBezierSegment(QPointF(0.4, 0.1), QPointF(0.6, 0.9), QPointF(1.0, 1.0));
    
        } else if (curveType == QEasingCurve::TCBSpline) {
            //TCB 样条曲线
            curve.addTCBSegment(QPointF(0.0, 0.0), 0, 0, 0);
            curve.addTCBSegment(QPointF(0.3, 0.4), 0.2, 1, -0.2);
            curve.addTCBSegment(QPointF(0.7, 0.6), -0.2, 1, 0.2);
            curve.addTCBSegment(QPointF(1.0, 1.0), 0, 0, 0);
        }
    
        return curve;
    }
    
    void Window::createCurveIcons()
    {
        QPixmap pix(m_iconSize);
        QPainter painter(&pix);
    
        //渐变色
        QLinearGradient gradient(0,0, 0, m_iconSize.height());
        gradient.setColorAt(0.0, QColor(240, 240, 240));
        gradient.setColorAt(1.0, QColor(224, 224, 224));
        QBrush brush(gradient);
        const QMetaObject &mo = QEasingCurve::staticMetaObject;
        //枚举转文字
        QMetaEnum metaEnum = mo.enumerator(mo.indexOfEnumerator("Type"));
    
        // Skip QEasingCurve::Custom
        for (int i = 0; i < QEasingCurve::NCurveTypes - 1; ++i) {
            painter.fillRect(QRect(QPoint(0, 0), m_iconSize), brush);
            //动画曲线
            QEasingCurve curve = createEasingCurve((QEasingCurve::Type) i);
            painter.setPen(QColor(0, 0, 255, 64));
            qreal xAxis = m_iconSize.height()/1.5;
            qreal yAxis = m_iconSize.width()/3;
    
            //X轴、y轴
            painter.drawLine(0, xAxis, m_iconSize.width(),  xAxis);
            painter.drawLine(yAxis, 0, yAxis, m_iconSize.height());
    
    
            //比例为icon的一半
            qreal curveScale = m_iconSize.height()/2;
    
            painter.setPen(Qt::NoPen);
    
            // start point 开始点
            painter.setBrush(Qt::red);
    
    
            QPoint start(yAxis, xAxis - curveScale * curve.valueForProgress(0));
            painter.drawRect(start.x() - 1, start.y() - 1, 3, 3);
    
            // end point 结束点
            painter.setBrush(Qt::blue);
            QPoint end(yAxis + curveScale, xAxis - curveScale * curve.valueForProgress(1));
            painter.drawRect(end.x() - 1, end.y() - 1, 3, 3);
    
            //绘制路径
            QPainterPath curvePath;
            curvePath.moveTo(start);
            for (qreal t = 0; t <= 1.0; t+=1.0/curveScale) {
                QPoint to;
                to.setX(yAxis + curveScale * t);
                to.setY(xAxis - curveScale * curve.valueForProgress(t));
                curvePath.lineTo(to);
            }
    
            //绘制曲线名称
            painter.setRenderHint(QPainter::Antialiasing, true);
            painter.strokePath(curvePath, QColor(32, 32, 32));
            painter.setRenderHint(QPainter::Antialiasing, false);
            QListWidgetItem *item = new QListWidgetItem;
            item->setIcon(QIcon(pix));
            item->setText(metaEnum.key(i));
            m_ui.easingCurvePicker->addItem(item);
        }
    }
    
    void Window::startAnimation()
    {
        //开启动画
        m_anim->setStartValue(QPointF(0, 0));
        m_anim->setEndValue(QPointF(100, 100));
        m_anim->setDuration(2000);
        m_anim->setLoopCount(-1); // forever
        m_anim->start();
    }
    
    void Window::curveChanged(int row)
    {
        //被点击的曲线
        QEasingCurve::Type curveType = (QEasingCurve::Type)row;
        m_anim->setEasingCurve(createEasingCurve(curveType));
        m_anim->setCurrentTime(0);
    
        bool isElastic = curveType >= QEasingCurve::InElastic && curveType <= QEasingCurve::OutInElastic;
        bool isBounce = curveType >= QEasingCurve::InBounce && curveType <= QEasingCurve::OutInBounce;
    
        //判断是否存振幅、周期和过冲
        m_ui.periodSpinBox->setEnabled(isElastic);
        m_ui.amplitudeSpinBox->setEnabled(isElastic || isBounce);
        m_ui.overshootSpinBox->setEnabled(curveType >= QEasingCurve::InBack && curveType <= QEasingCurve::OutInBack);
    }
    
    void Window::pathChanged(QAbstractButton *button)
    {
    
        const int index = m_ui.buttonGroup->id(button);
        //设置动画对象 是圆还是直线
        m_anim->setPathType(Animation::PathType(index));
    }
    
    void Window::periodChanged(double value)
    {
        QEasingCurve curve = m_anim->easingCurve();
        curve.setPeriod(value);
        m_anim->setEasingCurve(curve);
    }
    
    void Window::amplitudeChanged(double value)
    {
        QEasingCurve curve = m_anim->easingCurve();
        curve.setAmplitude(value);
        m_anim->setEasingCurve(curve);
    }
    
    void Window::overshootChanged(double value)
    {
        QEasingCurve curve = m_anim->easingCurve();
        curve.setOvershoot(value);
        m_anim->setEasingCurve(curve);
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • /easing/window.h
    #include 
    
    #include "ui_form.h"
    #include "animation.h"
    
    class PixmapItem : public QObject, public QGraphicsPixmapItem
    {
        Q_OBJECT
        Q_PROPERTY(QPointF pos READ pos WRITE setPos)
    public:
        PixmapItem(const QPixmap &pix) : QGraphicsPixmapItem(pix)
        {
        }
    };
    
    class Window : public QWidget {
        Q_OBJECT
    public:
        Window(QWidget *parent = nullptr);
    
    private slots:
        //动画曲线修改
        void curveChanged(int row);
    
        //路径变化
        void pathChanged(QAbstractButton *button);
    
        //振幅改变处理
        void periodChanged(double);
        //周期改变处理
        void amplitudeChanged(double);
        //过冲处理
        void overshootChanged(double);
    
    private:
        //创建曲线对应的icon,放到list中
        void createCurveIcons();
        //开启动画
        void startAnimation();
    
        Ui::Form m_ui;
        //场景对象
        QGraphicsScene m_scene;
        //场景中的元素
        PixmapItem *m_item;
        //自定义动画对象
        Animation *m_anim;
        //listview的icon大小
        QSize m_iconSize;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    4.实现过程分析

    • 官方demo使用自定义的Animation继承QPropertyAnimation,实现了updateCurrentTime虚函数来实现圆的动作。

    • setEasingCurve对动画类设置查直曲线,其中曲线有多种类型见QEasingCurve类中枚举

    • new Animation(m_item, “pos”);时候指定了pos属性,这是QWidget中的属性,如果要改变别的属性,怎么查。

      我们可以看QWidget头文件中使用Q_PROPERTY的属性即可。

    • createCurveIcons中绘制模拟插值曲线的实现很精妙,大家可以抄袭。

    • QEasingCurve内置很多插值曲线,但是常用的就几种

  • 相关阅读:
    QT+OSG/osgEarth编译之五十一:osgShadow+Qt编译(一套代码、一套框架,跨平台编译,版本:OSG-3.6.5工具库osgShadow)
    综述:大规模小目标检测
    DPDK初始化
    【排序算法】快速排序(C语言)
    接口测试面试秘籍,一套搞定接口测试
    C++中的类、结构体、指针和引用
    QT modbus rtu 拖动主界面时,modbus的槽函数无法响应
    Jenkins 相关内容
    IO作业:readdir、closedir、opendir、要求输入目录的路径后,能够打印出指定路径下所有文件的详细信息,类似ls -l
    JAVA【设计模式】责任链模式
  • 原文地址:https://blog.csdn.net/hiwoshixiaoyu/article/details/126286503