Forcing QGraphicsItem To Stay Put [duplicate]
Asked Answered
D

2

7

I have a QGraphicsScene that is filled with QGraphicsItems, and the user is able to pan and zoom around to inspect all of the various QGraphicsItems. However, I would like to have a QGraphicsTextItem label that always stays put at the top left of the screen. Ignoring the zooms is easy, as I can just setFlags(QGraphicsItem::ItemIgnoresTransformations), but I've yet to figure out how to force the position to stay at the top-left. What's the best way to make my label "float" in the same place?

Dworman answered 29/4, 2011 at 3:20 Comment(1)
see also #17373710Terrier
F
3

Perhaps you just want to put a regular QLabel right on the view instead of trying to make a part of the scene stay in one place as discussed in this question.

Note: As mentioned in another answer, this trick will often not work with hardware accelerated views. In these cases, you will need to make the text items a part of the scene.

Faden answered 29/4, 2011 at 7:32 Comment(0)
W
7

I think the only (realiable) way to do that is to recalculate position for your text item every frame. To do this, simply subclass QGraphicsView, override paintEvent and use QGraphicsView::mapToScene() to calculate new position. Something like:

void MyGraphicsView::paintEvent(QPaintEvent*)
{
    QPointF scenePos = mapToScene(0,0); // map viewport's top-left corner to scene
    m_textItem->setPos(scenePos);
}

I have done this many many times and it has worked very well.

Of course you could just create normal QLabel like Arnold Spence mentions in his answer. However, this won't work in many situations (e.g. if you really want to place label on top of graphics view and you are using OpenGL-accelerated viewport).

Were answered 29/4, 2011 at 10:17 Comment(4)
I was think of doing this, but won't the setPos call trigger an update, which will trigger a paintEvent, which will call setPos, etc..?Dworman
No it won't. Give it a try and you will see :).Were
Question, this requires me to re-implement the whole paintEvent for a scene? I would still like everything else within the scene to behave as usual. Calling QGraphicsView::paintEvent() in the beginning of my custom paintEvent() and then adding my extra code results in a flickering behaviour, since the original paintEvent first sets a position which I then set it to my custom position.Babylon
This solution has bad performance and architectural implications. The index of the scene needs to be refreshed every time you move the item. You're also breaking the model-view paradigm: the view is constantly messing with the model. While it will work with multiple views due to serial nature of the processing in the GUI thread, it's only a happy coincidence.Postulant
F
3

Perhaps you just want to put a regular QLabel right on the view instead of trying to make a part of the scene stay in one place as discussed in this question.

Note: As mentioned in another answer, this trick will often not work with hardware accelerated views. In these cases, you will need to make the text items a part of the scene.

Faden answered 29/4, 2011 at 7:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.