无法在 qgraphicsItem 中对 QTransform 进行动画处理

Can't animate QTransform in qgraphicsItem

本文关键字:动画 处理 QTransform 中对 qgraphicsItem      更新时间:2023-10-16

我正在尝试在GraphicsScene中做一些3D动画,例如,使用动画框架在GraphicsScene中旋转图片(使用class,从qPixmapItemQObject子类,如果它很重要的话(。

一切正常,直到我想绕垂直轴旋转图片。无法通过 item.rotate(( 执行此操作,所以我正在使用 QTranform .

问题是这样做根本不会动画任何东西。我做错了什么?

附言我不想为此使用 OpenGl。

这是我的做法。这种方式适用于动画更简单的属性,如pos、旋转(通过rotationsetRotation(

我的代码 :

// hybrid graphicsSceneItem, supporting animation 
class ScenePixmap : public QObject, public QGraphicsPixmapItem
{
    Q_OBJECT
    Q_PROPERTY(QTransform transform READ transform WRITE setTransform)
public:
    ScenePixmap(const QPixmap &pixmap, QObject* parent = NULL, QGraphicsItem* parentItem = NULL):
        QObject(parent),
        QGraphicsPixmapItem(pixmap, parentItem)
    {}
};

以下是我设置场景和动画的方法:

//setup scene
//Unrelated stuff, loading pictures, etc.
            scene = new QGraphicsScene(this);
        foreach(const QPixmap& image, images)
        {
            ScenePixmap* item = new ScenePixmap(image);
            item->moveBy(70*i, 0);
            i++;
            this->images.append(item);
            scene->addItem(item);
        }
    }
    ui->graphicsView->setBackgroundBrush(QBrush(Qt::black, Qt::SolidPattern));
    ui->graphicsView->setScene(scene);
    //setup animation
QTransform getTransform()
{
    QTransform transform;
    transform.rotate(-30, Qt::ZAxis);//also tried transform = transform.rotate(...)
    return transform;
}
QAbstractAnimation* SetupRotationAnimation(ScenePixmap* pixmapItem)
{
    QPropertyAnimation* animation = new QPropertyAnimation(pixmapItem, "transform");
    animation->setDuration(1400);
    animation->setStartValue( pixmapItem->transform());
    animation->setEndValue(getTransform());//here i tried to multiply with default transform , this does not work either
    return animation;
}

这是我开始动画的方式:

void MainWindow::keyPressEvent ( QKeyEvent * event )
{
    if((event->modifiers() & Qt::ControlModifier))
    {
        QAnimationGroup* groupAnimation = new QParallelAnimationGroup();

        foreach(ScenePixmap* image, images)
        {
            groupAnimation->addAnimation( SetupRotationAnimation(image));
        }
        groupAnimation->start(QAbstractAnimation::DeleteWhenStopped);
    }
}

编辑[解决]感谢达科·马克西莫维奇:

这是为我工作的代码:

QGraphicsRotation* getGraphicRotation()
{
    QGraphicsRotation* transform = new QGraphicsRotation(this);
    transform->setAxis(Qt::YAxis);
    return transform;
}
QAbstractAnimation* SetupRotationAnimation(ScenePixmap* pixmapItem)
{
    QGraphicsRotation* rotation = getGraphicRotation();
    QPropertyAnimation* animation = new QPropertyAnimation(rotation, "angle");
    animation->setDuration(1400);
    animation->setStartValue( 0);
    animation->setEndValue(45);
    pixmapItem->setTransformOriginPoint(pixmapItem->boundingRect().center());
    QList<QGraphicsTransform*> transfromations = pixmapItem->transformations();
    transfromations.append(rotation);
    pixmapItem->setTransformations(transfromations);
    return animation;
}

我看到你使用QTransform。如果你只想要一个旋转,并且是简单的旋转,最好使用 setRotate[不要忘记 setTransformOriginPoint]。

但是,如果你想记住许多旋转,例如围绕不同的变换点,那么你应该使用 QGraphicsTransform,即它的专用派生类 QGraphicsRotation,你可以通过在图形对象上调用 setTransformations 来应用它(你应该首先通过调用 o.transformations(( 来获取现有的变换,附加到这个,然后调用 setTransformations;如果你保留指向添加的变换的指针,你以后也可以直接更改(。

从您发布的代码中,我看不到您的错误来自哪里,但是通过使用专门的功能,您可以避免一些常见问题。

附言我还看到您没有在发布的代码中使用 prepareGeometryChange,因此请注意,这在转换对象时是必要的。

问题很简单。 QVariantAnimationQPropertyAnimation不支持QTransform。哎呀,他们目前甚至不支持无符号整数。仅此而已。根据Qt文档:

如果需要插值其他变体类型(包括自定义类型(,则必须自行为这些变体类型实现插值。为此,您可以为给定类型注册插值器函数。此函数采用 3 个参数:起始值、结束值和当前进度。

生成这样的插值器可能不是那么简单。请记住,您必须在两个矩阵之间"混合",同时保持矩阵的正交性和视觉效果。您需要将矩阵分解为单独的沿轴旋转、缩放、倾斜等子矩阵,然后分别插值每个子矩阵。难怪Qt的人没有这样做。做逆问题可能要容易得多:通过组合必要的旋转、平移等,生成所需的转换矩阵作为某个参数 t 的函数,所有这些都作为 t 的(可能是常数(函数给出。

仅仅因为QVariant可以携带类型并不意味着默认插值器支持它。可能应该为此发出运行时警告。