【问题标题】:QGraphicsItem: when paint function is calledQGraphicsItem:调用绘制函数时
【发布时间】:2013-09-02 22:48:19
【问题描述】:

我正在使用 QGraphicsView、QGraphicsScene 和 QGraphicsItem 创建动画。有人可以在调用paint函数时解释我吗?虽然我没有更改项目的变量,但每 ≈100 毫秒调用一次绘制函数。我可以停止它,以便我可以在需要时重新绘制该项目吗?

【问题讨论】:

    标签: qt graphics


    【解决方案1】:

    您以错误的方式接近它。仅在需要时才应重新绘制该项目 - 当您更改其外观或位置时。那是你打电话给QGraphicsItem::update()的时候。其余的将为您处理。看来你把事情复杂化了。

    请注意,您需要在 paint() 方法中确定动画的当前时间相关参数,或者“接近”它(例如,在调用 update() 之前),使用实际时间!如果您的动画源自QAbstractAnimation,那么它已经为您完成了。如果不是,那么您必须自己使用QElapsedTimer

    相关的 Qt 文档说:

    当当前时间改变时,动画框架调用updateCurrentTime()。通过重新实现该函数,您可以跟踪动画进度。请注意,调用之间的间隔和调用此函数的次数都没有定义;不过,通常每秒更新 60 次。

    这意味着 Qt 将尽最大努力制作动画。动画报告的 currentTime 是事件循环中动画更新那一刻的最新时间快照。这几乎就是你想要的。

    处理这一切的最简单方法是将QVariantAnimationQGraphicsObject 结合使用。下面是一个例子。您可以拥有自己的插槽并以其他方式对其进行修改,而不是旋转对象。您还可以使用自定义的QVariantAnimation,而不是使用信号槽连接,将自定义的QGraphicsItem 派生类作为目标。

    main.cpp

    #include <QApplication>
    #include <QGraphicsScene>
    #include <QGraphicsView>
    #include <QGraphicsObject>
    #include <QPropertyAnimation>
    #include <QGraphicsRectItem>
    
    class EmptyGraphicsObject : public QGraphicsObject
    {
    public:
        EmptyGraphicsObject() {}
        QRectF boundingRect() const { return QRectF(0, 0, 0, 0); }
        void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
    };
    
    class View : public QGraphicsView
    {
    public:
        View(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent) {
            setRenderHint(QPainter::Antialiasing);
        }
        void resizeEvent(QResizeEvent *) {
            fitInView(-2, -2, 4, 4, Qt::KeepAspectRatio);
        }
    };
    
    void setupScene(QGraphicsScene &s)
    {
        QGraphicsObject * obj = new EmptyGraphicsObject;
        QGraphicsRectItem * rect = new QGraphicsRectItem(-1, 0.3, 2, 0.3, obj);
        QPropertyAnimation * anim = new QPropertyAnimation(obj, "rotation", &s);
        s.addItem(obj);
        rect->setPen(QPen(Qt::darkBlue, 0.1));
        anim->setDuration(2000);
        anim->setStartValue(0);
        anim->setEndValue(360);
        anim->setEasingCurve(QEasingCurve::InBounce);
        anim->setLoopCount(-1);
        anim->start();
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QGraphicsScene s;
        setupScene(s);
        View v(&s);
        v.show();
        return a.exec();
    }
    

    【讨论】:

      【解决方案2】:

      你可以设置 QGraphicsView 的 viewportUpdateMode 来改变它的更新方式。选项是:-

      • QGraphicsView::FullViewportUpdate
      • QGraphicsView::MinimalViewportUpdate
      • QGraphicsView::SmartViewportUpdate
      • QGraphicsView::BoundingRectViewportUpdate
      • QGraphicsView::NoViewportUpdate

      Qt docs explains 不同选项的作用,但如果您想要完全控制,只需设置为 QGraphicsView::NoViewportUpdate 并使用 QTimer 事件自行控制。

      【讨论】:

      • viewportUpdateMode() 被忽略了,至少在我的情况下
      猜你喜欢
      • 1970-01-01
      • 2016-02-29
      • 2017-07-26
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多