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.