QGraphicsItem: когда вызывается функция рисования

Я создаю анимацию с помощью QGraphicsView, QGraphicsScene и QGraphicsItem. Может кто-нибудь объяснить мне, когда вызывается функция рисования? Хотя я не изменяю переменные элемента, функция рисования вызывается каждые ≈100 мс. Могу ли я остановить это, чтобы я мог перекрасить предмет, когда захочу?

2 ответа

Вы подходите к этому неправильно. Предмет следует перекрашивать только при необходимости - когда вы меняете его внешний вид или местоположение. Вот когда вы звоните QGraphicsItem::update(), Остальное будет обработано для вас. Кажется, вы слишком усложняете вещи.

Обратите внимание, что вам нужно определить текущий зависящий от времени параметр анимации в paint() метод, или "близко" к нему (скажем, прямо перед update() называется), используя фактическое время! Если ваша анимация получена из QAbstractAnimation, это уже сделано для вас. Если это не так, то вам придется использовать QElapsedTimer сам.

Соответствующая документация Qt гласит:

Фреймворк анимации вызывает updateCurrentTime() когда текущее время изменилось. Реализовав эту функцию, вы можете отслеживать ход анимации. Обратите внимание, что ни интервал между вызовами, ни количество вызовов этой функции не определены; хотя, как правило, это будет 60 обновлений в секунду.

Это означает, что Qt будет делать анимацию с максимальной отдачей. CurrentTime, сообщаемый анимацией, является самым последним моментальным снимком на момент обновления анимации в цикле событий. Это в значительной степени то, что вы хотите.

Самый простой способ справиться со всем этим - использовать QVariantAnimation с QGraphicsObject, Пример ниже. Вместо того, чтобы вращать объект, вы можете иметь свой собственный слот и модифицировать его другим способом. Вы также можете вместо использования разъема для подключения 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();
}

Вы можете установить viewportUpdateMode QGraphicsView, чтобы изменить способ его обновления. Варианты: -

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

Документы Qt объясняют, что делают различные опции, но если вы хотите получить полный контроль, просто установите QGraphicsView::NoViewportUpdate и управляйте им самостоятельно, используя событие QTimer.

Другие вопросы по тегам