c++qtinheritanceqt5qproperty

Using an existing Q_PROPERTY to animate QGraphicsItem inheriting QObject


I have 2 classes, one MainWindow in which we draw in a QGraphicsView a circle (which intend to become a button !) created thanks to an other class. The class MyCircle inherits from QObject and QGraphicsItem since I want to make animation.

My issue is the following :

My goal is first to make a simple animation on my drawing : make it smaller then it goes back to the original size. So I suppose I should use the property geometry, already existing in the QObject class.

To do this I write in my MainWindow.ccp

animationBoutonRondTaille = new QPropertyAnimation(roundButton, "geometry");
animationBoutonRondTaille->setDuration(1000);
animationBoutonRondTaille->setKeyValueAt(0, QRect(-100, -100, 200, 200));
animationBoutonRondTaille->setKeyValueAt(0.5, QRect(-80,-80,160,160));
animationBoutonRondTaille->setKeyValueAt(1, QRect(-100, -100, 200, 200));
animationBoutonRondTaille -> start();

If I don't include

class MyCircle : public QObject, public QGraphicsItem
{
    Q_OBJECT
    Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry)
/.../
}

I got the following error message :

QPropertyAnimation: you're trying to animate a non-existing property geometry of your QObject

But if I do, i got this one :

'class MyCircle' has no member named 'geometry'/'setgeometry'

What is the purpose of inheriting QObject if I have to define all by myself the geometry property ?

Hope you can help me, and sorry if my question is vague, it's the first for me so I don't really know what you expect.

Thanks a lot if you take time to answer.


Solution

  • You have to implement the geometry and setGeometry methods, the Q_PROPERTY are used to call functions using the setProperty("geometry", some_value) and property("geometry") functions that are used internally in QPropertyAnimation, as well as in the Setter function (in this case setGeometry) you must call update() to update the graph.

    mycircle.h

    #ifndef MYCIRCLE_H
    #define MYCIRCLE_H
    
    #include <QGraphicsItem>
    #include <QObject>
    #include <QPainter>
    #include <QStyleOptionGraphicsItem>
    
    class MyCircle : public QObject, public QGraphicsItem
    {
        Q_OBJECT
        Q_PROPERTY(QRect geometry READ geometry WRITE setGeometry)
        Q_INTERFACES(QGraphicsItem)
    public:
        explicit MyCircle(QObject *parent = nullptr);
    
        QRect geometry() const;
        void setGeometry(const QRect &value);
    
        QRectF boundingRect() const;
        void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
    
    private:
    
        QRect rect;
    };
    
    #endif // MYCIRCLE_H
    

    mycircle.cpp

    #include "mycircle.h"
    
    MyCircle::MyCircle(QObject *parent) : QObject(parent)
    {
        rect = QRect(0, 0, 100, 100);
    }
    
    QRect MyCircle::geometry() const
    {
        return rect;
    }
    
    void MyCircle::setGeometry(const QRect &value)
    {
        if(rect!=value){
            rect = value;
            update();
        }
    }
    
    QRectF MyCircle::boundingRect() const
    {
        return QRectF(rect);
    }
    
    
    void MyCircle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
               QWidget *widget)
    {
        Q_UNUSED(option)
        Q_UNUSED(widget)
        painter->setBrush(QBrush(Qt::red));
        painter->drawEllipse(rect);
    }
    

    A complete example can be found here