【问题标题】:Can't animate QTransform in qgraphicsItem无法在 qgraphicsItem 中为 QTransform 设置动画
【发布时间】:2013-08-31 05:20:15
【问题描述】:

我正在尝试在 GraphicsScene 中制作一些 3D 动画,例如,使用 Animation 框架旋转 GraphicsScene 中的图片(使用类,从 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);

    }
}

编辑[已解决] 感谢 Darko Maksimovic:

这是为我解决的代码:

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;
}

【问题讨论】:

  • 你在哪里打电话SetupRotationAnimation
  • 你知道,我老实说无法确定“transfromations”是否是一个聪明的双关语(对于现有的转换列表你'重新加载像素图)...或者只是相同的错字重复了三遍。

标签: c++ qt animation qgraphicsview


【解决方案1】:

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

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

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

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

【讨论】:

  • 成功了,谢谢!我将更新问题以指出解决方案
  • 对旋转进行动画处理并不是“更好”,否则它根本无法工作 - 设计使然。
【解决方案2】:

问题很简单。 QVariantAnimationQPropertyAnimation 不支持 QTransform。哎呀,他们现在甚至不支持无符号整数。这就是它的全部。根据 Qt 文档:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-26
    • 2015-07-30
    • 2017-12-10
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多