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.

    0_1530068277668_1.gif

    But my code can only do once rotation., and it stopped.

    0_1530068697594_2.gif

    Can someone give me some advice?

    (Below are the two png picture the code needs)
    0_1530068817274_background.png
    0_1530068825866_pointer.png



  • 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 in timerEvent, it must run the paint.



  • 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.



  • @Limer

    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.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.