QtWidgets实现旋转动画

134 阅读1分钟

原理:利用自定义属性+QPropertyAnimation+自定义绘制实现旋转动画

代码如下:

// RotateAnimateButton.hpp
class RotateAnimateButton : public QPushButton {
    Q_OBJECT
    Q_PROPERTY(int rotate READ getRotate WRITE setRotate FINAL)
    Q_PROPERTY(QString url READ getPixmapUrl WRITE setPixmapUrl DESIGNABLE true STORED true)
public:
    enum class RotateDirection { Clockwise, Counterclockwise };

    explicit RotateAnimateButton(QWidget* parent = nullptr);

    inline QString getPixmapUrl() {
        return m_url;
    }
    void setPixmapUrl(const QString& url);

    inline void setRotateDirection(RotateDirection direction) {
        m_direction = direction;
    }

    inline int getRotate(){ return m_rotate; }
    void setRotate(int rotate);

protected:
    void paintEvent(QPaintEvent* event) override;

private:
    QPropertyAnimation* m_animation = nullptr;
    QString m_url;
    QPixmap m_pixmap;
    int m_rotate = 0;
    RotateDirection m_direction = RotateDirection::Clockwise;
};

// RotateAnimateButton.cpp
RotateAnimateButton::RotateAnimateButton(QWidget* parent) : QPushButton(parent) {
    m_animation = new QPropertyAnimation(this, "rotate", this);
    m_animation->setDuration(600);
    m_animation->setStartValue(0);
    m_animation->setEndValue(360);
    connect(this, &QPushButton::clicked, [this]() {
        m_animation->start();
    });
}

void RotateAnimateButton::setPixmapUrl(const QString& path) {
    m_pixmap = QPixmap(path);
    update();
}

void RotateAnimateButton::setRotate(int rotate) {
    m_rotate = rotate;
    update();
}

void RotateAnimateButton::paintEvent(QPaintEvent* event) {
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
    painter.translate(width() / 2, height() / 2); // 将旋转中心设为组件中心
    painter.rotate(m_direction == RotateDirection::Clockwise ? m_rotate : -m_rotate); // 画笔旋转
    painter.translate(-width() / 2, -height() / 2); // 将旋转中心重置
    painter.drawPixmap(0, 0, m_pixmap);
}