Solved How to make a QGraphicsItem animation?
-
#ifndef ITEM_H #define ITEM_H #include <QGraphicsItem> #include <QGraphicsTextItem> #include <QPainter> #include <QPixmap> class Item : public QObject, public QGraphicsItem { Q_OBJECT public: Item(QObject* parent = 0) : QObject(parent) { m_bgPixmap.load(":/two/background.png"); m_pointerPixmap.load(":/two/pointer.png"); m_textItem = new QGraphicsTextItem("0", this); m_textItem->setPos(-15, 20); m_value = 0; startTimer(1000); } virtual void timerEvent(QTimerEvent*) { m_value += 30; if (m_value == 360) m_value = 0; m_textItem->setPlainText(QString::number(m_value)); } virtual QRectF boundingRect() const { qreal adjust = 2; return QRectF(-m_bgPixmap.width() / 2 - adjust, -m_bgPixmap.height() / 2 - adjust, m_bgPixmap.width() + adjust * 2, m_bgPixmap.height() + adjust * 2); } protected: virtual void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { painter->drawPixmap(boundingRect().topLeft() + QPointF(11, 11), m_bgPixmap); QPointF pf = boundingRect().topLeft() + boundingRect().bottomRight(); painter->translate(pf); painter->rotate(m_value); painter->translate(-pf); painter->drawPixmap(boundingRect().topLeft() + boundingRect().bottomRight() + QPointF(-20, -19), m_pointerPixmap); } private: QPixmap m_bgPixmap; QPixmap m_pointerPixmap; QGraphicsTextItem* m_textItem; int m_value; }; #endif // ITEM_H
Above codes customize an item, what I want is the below result. The pointer can complete 360 degree rotation.
But my code can only do once rotation., and it stopped.
Can someone give me some advice?
(Below are the two png picture the code needs)
-
How should Qt know that it needs to repaint the needle, just because you change m_value? You have to tell it.
Easiest is to call update()
If you want to optimize a bit, you can call update with the exact rectangle that needs to be redrawn.
If you make the needle a separate item, you could just call update() on that item. -
@Asperamanca Actually, I test it, if I run
setPlainText
intimerEvent
, it must run thepaint
. -
But that only triggers painting for the area of the text item. That's why you see artifacts of the needle over and around the text in your animation, but nowhere else.
-
As @Asperamanca said, you could just call update() after setPlainText(). like this:
m_textItem->setPlainText(QString::number(m_value)); update();
-
@Asperamanca Yes, you are right. Thanks a lot.