這篇文章展示瞭如何使用自定義的型別實現動畫。自定義型別的動畫效果使用QVariantAnimation類實現,需要實現一個插值函式。Qt提供了多個介面,主要有如下兩種方法:
- 實現QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const函式;
- 使用template <typename T> void qRegisterAnimationInterpolator(QVariant (*func)(const T &, const T &, qreal))函式或void QVariantAnimation::registerInterpolator(Interpolator func, int interpolationType)函式註冊自定義插值函式。
本例使用第一種方法,實現了一個按鈕在兩點之間沿著圓弧從起始點運動到結束點的效果。截圖示意如下:
標頭檔案。自定義型別是MMyType,我們重寫了interpolated(...)函式:
struct MMyType { QPointF pos; }; Q_DECLARE_METATYPE(MMyType); class MDiyAnimation : public QVariantAnimation { Q_OBJECT public: MDiyAnimation(QObject *parent = 0); private: QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const override; };
CPP檔案:
MDiyAnimation::MDiyAnimation(QObject *parent) : QVariantAnimation(parent) { } QVariant MDiyAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const { MMyType ifrom = from.value<MMyType>(); MMyType ito = to.value<MMyType>(); QPointF ftvec = ifrom.pos - ito.pos; qreal radius = 0.5 * qSqrt(QPointF::dotProduct(ftvec, ftvec)); QPointF center = (ifrom.pos + ito.pos) * 0.5; qreal angle = qAtan2(ftvec.y(), ftvec.x()) + M_PI * progress; MMyType newPos; newPos.pos.setX(center.x() + radius * qCos(angle)); newPos.pos.setY(center.y() + radius * qSin(angle)); return QVariant::fromValue<MMyType>(newPos); }
在主視窗建構函式使用如下。程式碼中QtTest是主視窗類,ui.pbTest是按鈕控制元件:
QtTest::QtTest(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); MDiyAnimation* ani = new MDiyAnimation(this); connect(ani, &MDiyAnimation::valueChanged, this, [this](const QVariant& v) { QPointF pp = v.value<MMyType>().pos; ui.pbTest->setGeometry(pp.x(), pp.y(), ui.pbTest->width(), ui.pbTest->height()); }); ani->setStartValue(QVariant::fromValue<MMyType>({ ui.pbTest->pos() })); ani->setEndValue(QVariant::fromValue<MMyType>({ QPointF(400, 400) })); ani->setDuration(5000); ani->setLoopCount(-1); ani->start(); }