【问题标题】:How to animate line around fixed point in Qt?如何在Qt中围绕固定点制作动画?
【发布时间】:2018-07-20 13:51:46
【问题描述】:

我正在尝试围绕 Qt 中的一个固定点制作一条线。我假设我需要使用 QPropertyAnimation 类来执行此操作,但无法确定要使用哪个属性。

为了清楚起见,这就是我想要做的。

|        (5, 10)
|       /
|      /
|     /
|    /          (10, 5)   
|   /          .
|  /
| /           
|/
|--------------------------
 ^
 |---(0,0)

给定 (x1, y1) = (0, 0) & (x2, y2) = (5, 10),这将是动画的第一帧。然后我想从 (x1, y1), (x2, y2), (其中 (x1, y1) 是线的一端, (x2, y2) 是另一端) 到 (x1) 做一个平滑的动画, y1), (x3, y3),其中 (x3, y3) = (10, 5)。类似于时钟指针的动画方式。在有人发布 模拟时钟 示例之前,它使用了一个旋转的 pixmap,这不是我需要的。

我没有找到很多关于 Qt 动画的信息,只有很多基本的 GUI 教程。

我尝试过以下操作

QPropertyAnimation *anim = new QPropertyAnimation(widget, "geometry")

这种方法的问题是,在这种技术中,小部件使用 ->setStartValue(startX, startY, ...) 在基于小部件的 (0, 0) 的 2 个点之间移动,并且不允许我将我的一条线保持在一个固定点。

QPropertyAnimation *anim = new QPropertyAnimation(widget, "rotation")

此方法的问题与几何相似,因为它沿 (0, 0) 点旋转所述小部件。

谁能告诉我如何达到预期的效果?

谢谢。

【问题讨论】:

  • 你是怎么画线的,你是用QPainter,还是QGraphicsLineItem,还是其他方法?
  • 理想情况下,我想使用 QGraphicsLineItem,但我愿意接受任何可以完成工作的事情。
  • 据我所见,您希望线相对于点 (0, 0) 旋转,对吗?
  • ... 有点...但我不是说使用“旋转”属性,因为我需要能够控制行长。旋转意味着我无法控制行长。使用转换的像素图(如模拟时钟示例),几何属性或旋转属性不是我想要的。您可以将其视为旋转线,同时能够控制线的长度。上述方法不允许我控制线路的长度。希望这很清楚。
  • 实际上,如果您知道如何使用 geomtry 或 rotation 属性来做到这一点,我会全力以赴,但已经尝试了很多方法,但都没有奏效。

标签: c++ qt qt5 qpropertyanimation qgraphicslineitem


【解决方案1】:

QGraphicsXXXItem 不支持 q-properties,因此它们不能直接与 QPropertyAnimation 一起使用。所以解决方案是创建一个继承QObjectQGraphicsLineItem的类,另外我们必须添加一个q-property来处理与该行关联的QLineFp2位置,如下所示:

lineitem.h

#ifndef LINEITEM_H
#define LINEITEM_H

#include <QGraphicsLineItem>
#include <QObject>

class LineItem: public QObject, public QGraphicsLineItem {
    Q_OBJECT
    Q_PROPERTY(QPointF p1 READ p1 WRITE setP1)
    Q_PROPERTY(QPointF p2 READ p2 WRITE setP2)

public:
    using QGraphicsLineItem::QGraphicsLineItem;

    QPointF p1() const {
        return  line().p1();
    }

    void setP1(const QPointF & p){
        QLineF l = line();
        l.setP1(p);
        setLine(l);
    }

    QPointF p2() const {
        return  line().p2();
    }

    void setP2(const QPointF & p){
        QLineF l = line();
        l.setP2(p);
        setLine(l);
    }
};

#endif // LINEITEM_H

ma​​in.cpp

#include "lineitem.h"

#include <QApplication>
#include <QGraphicsView>
#include <QPropertyAnimation>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene scene(-100, -100, 200, 200);
    QGraphicsView view(&scene);

    QGraphicsLineItem *item = scene.addLine(QLine(0, 100, 100, 0));
    item->setPen(QPen(Qt::red, 5));

    LineItem *lineItem = new LineItem(QLineF(QPointF(0, 0), QPointF(0, 100)));
    scene.addItem(lineItem);
    lineItem->setPen(QPen(Qt::green, 2));

    QPropertyAnimation *anim = new QPropertyAnimation(lineItem, "p2");
    anim->setStartValue(QPointF(0, 100));
    anim->setEndValue(QPointF(100, 0));
    anim->setDuration(2000);
    anim->start();

    view.resize(640, 480);
    view.show();
    return a.exec();
}

另一种方法是使用QVariantAnimation:

#include <QApplication>
#include <QGraphicsView>
#include <QPropertyAnimation>
#include <QGraphicsLineItem>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsScene scene(-100, -100, 200, 200);
    QGraphicsView view(&scene);

    scene.addLine(QLine(0, 100, 100, 0), QPen(Qt::green));

    QGraphicsLineItem *item = scene.addLine(QLine(0, 0, 0, 100));
    item->setPen(QPen(Qt::red, 5));

    QVariantAnimation * anim = new QVariantAnimation(&scene);
    anim->setStartValue(QPointF(0, 100));
    anim->setEndValue(QPointF(100, 0));
    anim->setDuration(2000);
    anim->start();

    QObject::connect(anim, &QVariantAnimation::valueChanged, [item](const QVariant & val){
        QLineF l = item->line();
        l.setP2(val.toPointF());
        item->setLine(l);
    });

    view.resize(640, 480);
    view.show();
    return a.exec();
}

【讨论】:

  • 任务很简单,如果你知道每个类的操作和要求,阅读以下内容:doc.qt.io/qt-5/animation-overview.html
  • qt 不是已经有类 QGraphicsObject 是 QGraphicsItem 和 QObject 的组合吗?
  • @AndrewKashpur 是的,您可以使用 QGraphicsObject,这是另一种选择,但我们说 缺点 是您必须实现 paint() 和 boundingRect() 方法。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 2022-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-20
相关资源
最近更新 更多