You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用QPropertyAnimation实现QLabel内QPixmap的连续90度旋转?

解决QLabel/QPixmap连续90度旋转动画的简便方法

嘿,刚接触Qt就搞动画确实容易懵,我之前折腾旋转动画的时候也卡过壳!QWidget本身没有内置的rotation属性,所以直接用QPropertyAnimation是不行的,但我们可以给QLabel自定义一个旋转属性,或者直接对QPixmap做动画,下面给你两种实用的方案:

方案一:自定义QLabel子类 + QPropertyAnimation(推荐,流畅高效)

这种方法是给QLabel加一个可被QPropertyAnimation驱动的rotation属性,在重绘时应用旋转,动画流畅度拉满。

1. 自定义带旋转属性的Label子类

先写头文件(比如RotatableLabel.h):

#ifndef ROTATABLELABEL_H
#define ROTATABLELABEL_H

#include <QLabel>

class RotatableLabel : public QLabel
{
    Q_OBJECT
    Q_PROPERTY(int rotation READ rotation WRITE setRotation NOTIFY rotationChanged) // 声明旋转属性

public:
    explicit RotatableLabel(QWidget *parent = nullptr);

    int rotation() const;

public slots:
    void setRotation(int newRotation);

signals:
    void rotationChanged(int rotation);

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    int m_rotation = 0; // 当前旋转角度
};

#endif // ROTATABLELABEL_H

然后实现cpp文件(RotatableLabel.cpp):

#include "RotatableLabel.h"
#include <QPainter>

RotatableLabel::RotatableLabel(QWidget *parent) : QLabel(parent) {}

int RotatableLabel::rotation() const
{
    return m_rotation;
}

void RotatableLabel::setRotation(int newRotation)
{
    if (m_rotation == newRotation)
        return;
    m_rotation = newRotation;
    emit rotationChanged(m_rotation);
    update(); // 触发重绘
}

void RotatableLabel::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter(this);

    // 关键:把旋转中心移到Label的中心
    painter.translate(rect().center());
    painter.rotate(m_rotation);
    painter.translate(-rect().center());

    // 绘制Pixmap(保持原有尺寸和对齐)
    if (!pixmap().isNull()) {
        painter.drawPixmap(rect(), *pixmap());
    } else {
        // 如果没有Pixmap,默认绘制文本
        QLabel::paintEvent(event);
    }
}

2. 用QPropertyAnimation实现连续90度旋转

在你的主窗口或者调用的地方,这样写:

#include "RotatableLabel.h"
#include <QPropertyAnimation>

// 假设你已经创建了RotatableLabel实例
RotatableLabel *label = new RotatableLabel(this);
label->setPixmap(QPixmap("your_image_path.png"));
label->resize(200, 200);
label->move(100, 100);

// 创建动画对象
QPropertyAnimation *anim = new QPropertyAnimation(label, "rotation");
anim->setDuration(500); // 每次旋转的时长(毫秒)
anim->setStartValue(0);
anim->setEndValue(90);

// 实现连续旋转:动画结束后重置角度并再次启动
connect(anim, &QPropertyAnimation::finished, [=](){
    label->setRotation(0); // 重置角度(避免角度无限累加)
    anim->start(); // 再次启动动画
});

// 启动动画
anim->start();

如果你想让旋转是累加的(比如0→90→180→270→0...),可以把finished槽改成:

connect(anim, &QPropertyAnimation::finished, [=](){
    int current = label->rotation();
    anim->setStartValue(current);
    anim->setEndValue(current + 90);
    anim->start();
});

方案二:直接操作QPixmap(适合简单场景)

如果不想自定义子类,也可以用QVariantAnimation直接更新QPixmap的旋转状态,但每次都要重新生成旋转后的Pixmap,性能略逊于方案一:

QLabel *label = new QLabel(this);
QPixmap originalPixmap("your_image_path.png");
label->setPixmap(originalPixmap);
label->resize(200, 200);

QVariantAnimation *anim = new QVariantAnimation();
anim->setDuration(500);
anim->setStartValue(0);
anim->setEndValue(90);

connect(anim, &QVariantAnimation::valueChanged, [=](const QVariant &value){
    int angle = value.toInt();
    // 生成旋转后的Pixmap(绕中心旋转)
    QPixmap rotated = originalPixmap.transformed(QTransform().rotate(angle), Qt::SmoothTransformation);
    label->setPixmap(rotated);
});

// 连续旋转的逻辑和方案一类似
connect(anim, &QVariantAnimation::finished, [=](){
    anim->setStartValue(anim->endValue());
    anim->setEndValue(anim->endValue().toInt() + 90);
    anim->start();
});

anim->start();

小提示

  • 旋转时用Qt::SmoothTransformation可以让图片旋转更平滑,尤其是非正方形图片
  • 如果你的QLabel是固定尺寸,方案一的性能会更好,因为它只是在绘制时做旋转运算,不需要每次生成新的Pixmap

内容的提问来源于stack exchange,提问作者gont_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:13:58