Search code examples
qtsignals-slotsqgraphicsitemqgraphicsscene

How to access a signal of QGraphicsItem from scene subclass


I need to read a signal emitted by a QGraphicsItem subclass, into a QGraphicsScene subclass.

Practical situation:

I have subclassed my QGraphicsScene, and many QGraphicsItem classes.

MyScene has a lot of properties reflecting changes of contained QGraphicsItems - including item size and position.

MyTextItem looks a little like this:

.h
class MyTextItem : public QGraphicsTextItem
{
Q_OBJECT
public:
    MyTextItem();
    ~MyTextItem() {}
    QSizeF getItemSize() const { return m_size; }
    void setItemSize(const QSizeF s) { m_size = s; }
signals:
    void textItemHasChanged();
private slots:
    void updateItemOnContentsChanged();
private:
    void updateTextOnPropertyChanges();
    QSizeF m_size;
};

.cpp
MyTextItem::MyTextItem()
{
    setTextInteractionFlags(Qt::TextEditorInteraction);
    connect(document(), SIGNAL(contentsChanged()), this, SLOT(updateItemOnContentsChanged()));
}
void MyTextItem::updateItemOnContentsChanged()
{
    updateTextOnPropertyChanges();
    emit textItemHasChanged();
}
void MyTextItem::updateTextOnPropertyChanges()
{
    qDebug("updating things like size or position");
}    

Testing the MyTextItem I can update its size and position when I type into the QGraphicsTextItem. (the only way to see it right now is to do another action that would force a refresh of properties - yet I know that works)

How do I propagate this at the scene class level ? (so I get instant updates)

I created a signal in my text item class textItemHasChanged();, but how can I connect it in the scene class ? (what would be the object ?)

The scene class... nothing special

class MyScene : public QGraphicsScene
{
    Q_OBJECT

public:
    MyScene (const qreal w = 300, const qreal h = 200, QObject* parent = 0);
    ~MyScene() {}
    // item add functions, item property functions, mouse overides
};

MyScene::MyScene(const qreal w, const qreal h, QObject *parent)
{
    setSceneRect(0, 0, w, h);
    connect(this, SIGNAL(selectionChanged()), this, SLOT(onSceneSelectionChanged()));
}

I would add a

    connect(???????, SIGNAL(textItemHasChanged()), this, SLOT(onSelectedItemsSizeChanged()));

But I don't know what the object would be...

How can I access the change in MyTextItem due to user typing text (document().contentsChanged()) from the scene class ?

Is the scene already aware of this signal ? (I mean, is it included in keyboard/mouse signals ?)

Or more general, how can I access a signal emitted by a QGraphicsItem, in the QGraphicsScene ?

I looked at QGraphicsScene::changed() - that signal is implemented from what I understand every time there is any sort of change...
Not sure how I can determine from there what has changed, and it may be very heavy-weight...
I added to MyTextItem: setFlags(QGraphicsItem::ItemSendsGeometryChanges); but I don't see how this will help.
Writing the MyTextItem::itemChange() function ... I still don't see how to get the information from the scene class.


Solution

  • the object would be the one which sent the signal, i.e. MyTextItem object.

    And answering to your general question: The way you can access to a signal emitted by a QGraphicsItem, in the QGraphicsScene is connecting the signal of the QGraphicsItem with a slot of the QGraphicsScene. Something like this:

    connect(graphicsItemObject, SIGNAL(graphicsItemSignal()), graphicsSceneObject, SLOT(graphicsSceneSlot()));
    

    I hope this can help you a little bit.