Will paint(), redraw everything from scene or will redraw only updated items in Qt?
-
I have QGraphicsView which contains many QGraphicsItem such as Rectangle, polylines. I have overriden paint() method. I am drawing QGraphicsItem using boost-graph. While drawing items, I am storing boost-graph pointer on every QGraphicsItem.
Now I am right clicking on some rectangle from scene and trying to hide it. While hiding it, I am trying to hide lines connected to it also. For that, I am taking boost-graph pointer stored at every item and iterating through it.
In boost graph, there is a flag isVisible, through setting-resetting it, I am hidding-unhidding that item.myView.cpp
void myClass:: DrawRect() { while(true) { // iterating thorugh boost-graph and finding co-ordinates myRect* _rect = new myRect(rect co-ordinates); _rect->setBrush(Qt::yellow); _rect->setPtr(boost-graph pointer); _scene->addItem(static_cast<QGraphicsRectItem*>(_rect)); } void myView::HideSelectedRectangle() // after choosing hide from right mouse click, control comes here { foreach(QGraphicsItem* currentItem, _scene->selectedItems()) { myRect* rItem = qgraphicsitem_cast<myRect*>(currentItem); if(rItem) { VertexDescriptor vPtr = rItem->getBoostPtr(); // getting boost-graph ptr // logic for making it hide // Question is how paint() will know about this QGraphicsItem that it is hidden? }; } }
myRect.cpp
```
void myRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { auto copied_option = *option; copied_option.state &= ~QStyle::State_Selected; auto selected = option->state & QStyle::State_Selected; QGraphicsRectItem::paint(painter, &copied_option, widget); if(selected) { painter->save(); painter->setBrush(Qt::NoBrush); painter->setPen(QPen(option->palette.windowText(), 0, Qt::SolidLine)); painter->drawPath(shape()); painter->restore(); } }
void myRect::setPtr(VertexDescriptor vIter) { this->boostPtr = vIter; } VertexDescriptor myRect::getPtr() { return boostPtr; }
myRect.h
class myRect: public QGraphicsRectItem { public: explicit myRect(); explicit myRect(QRectF &rectPoints,QGraphicsItem *parent = nullptr) : QGraphicsRectItem(rectPoints,parent){} void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setPtr(VertexDescriptor); VertexDescriptor getPtr(); VertexDescriptor boostPtr; }
Now assume I have made _isVisible = false (which is in boost-graph) for rectangle and some connected lines. And now I want to redraw view using paint(). And expecting, paint() should not draw those rectangle and lines which are marked as not visible.
Is paint() redraw every QGraphicsItem from view or it will redraw only those were updated ? How paint() will know, which shape should it draw and its co-ordinates ? Is it possible in my paint(), by checking QGraphicsItem's flag (isVisible) I can guide paint() which items to redraw and which not to redraw ?
-
@SGaist , @JonB Please help.
If you are confused, then I tell you in short, what I want ?
In my paint(), I want QGraphicsItem which are updated. Once I get those items, ( I have kept boost-graph pointer on each item) I can access boost-graph flag isVisible, and change it to false. And tell paint() method please draw it. paint() will see that flag and will not draw it. And I successfully hide that item. Is it possible ? -
Hi,
Why not make use of the setVisible method of the base class ?
-
@tushu
I have never used (or heard of) "boost graph". I can guess you are doing some sort of "shadowing" of graphics objects which it holds.The
paint()
you show is to (re-)paint amyRect
. So it does not "redraw every QGraphicsItem from view", it is called when amyRect
instance needs to be (re-)painted. It is notpaint()
's job to "redraw only those were updated". The framework notes whichGraphicsItem
s are updated and need repainting, and only callspaint()
on those marked changed/dirty.paint()
is being called on amyRect
, so that is how it "know, which shape should it draw and its co-ordinates".If you are saying boost graph has some "is visible" property on its objects, then presumably you should shadow that on your corresponding
QGraphicsItem
'svisible
property.It may sound like you are trying to do too much in your
paint()
method. You are supposed to do operations on theQGraphicsItem
s themselves, they just callpaint()
when you have changed something. -
@SGaist It will increse time complexity. I want to hide lines which are connected to rectangle. If those lines are connected to some other items then that also I need to hide. So I was told to use this approach. Simplly put flag isVisible = false and let do work to paint()
-
-
@tushu said in Will paint(), redraw everything from scene or will redraw only updated items in Qt?:
But can I get access of updated QGraphicsItem in paint() ?
I don't understand. You showed your
void myRect::paint(...)
. So thatmyRect
,this
, is theQGraphicsItem
being painted.I just want, updated item in paint().
You keep saying that.
paint()
is/should only be called on thoseQGraphicsItem
s which have been updated and need redrawing, so far as I know. -
@JonB From your post I understood that, paint() gets called only for updated/dirty items.
I was said that, if we hide rectangle by boost-graph then, we dont need to hide its text, its connected lines, their names. It will be hidden automatically. That's why I need updated item like this, so that I can get rItem's boost pointer, make it not visible and then paint() will see it is not visible , so wont draw it. Is this possible ?if(rItem) VertexDescriptor vPtr = rItem->getBoostPtr();
-
You need to call setVisible(false) or hide() at some point on each QGraphicsItem that you want hidden. The GraphicsView engine needs to know about it, otherwise you'll get funny effects, or just plain code that doesn't work.
Not knowing boost graph, I do hope they allow some way to call functions when a graph node's state changes. If this is the case, you can forward the visibility information of each graph node to it's corresponding QGraphicsItem.
The paint() function is for painting. It's not intended as a place to execute logic or change state. Sometimes that may be necessary, but mostly, it causes grief and bugs.
-
@tushu said in Will paint(), redraw everything from scene or will redraw only updated items in Qt?:
I was said that, if we hide rectangle by boost-graph then, we dont need to hide its text, its connected lines, their names. It will be hidden automatically.
If you mean the
QGraphicsItem
s, are those thingschildItem()
s of the rectangle? Then I assume it'svisible
status would be carried to its children?I don't think trying to deal in
myRect::paint()
with the painting or visibility of otherQGraphicsItem
s is a good idea/will work. -
@JonB @Asperamanca @SGaist
I want to hide R1. along with R1, I will have to hide L1,L2 and L3 also as they are connected to hidden item. R2 will also get hidden as it is not connected to any items after L1 and L2 gets hidden.
But R3 , R4 and L4 won't be hidden.
Is this possible with Parent-Child relationship ? ( Means, here if we make R1 as parent and L1,L2 and L3 are children, then if R1 is hidden then its children will be hidden automatically ) -
@tushu
A picture is worth a thousand words! It would have helped if you had shown this from the start!I believe this can be done, but never tried it. Why don't you give it a brief try?!
The "wrinkle" here is that clearly all the other child items are outside the bounding rect of the
R1
parent rectangle.If you do it by parent-child, I am thinking you would need to expand the parent rect's
boundingRect()
to include theQGraphicsItem::childrenBoundingRect()
. Normally children are supposed to be inside their parent, I don't know if your case is dealt with/works.Alternatively you should look at QGraphicsItemGroup, and in particular read through its Detailed Description. This may be what you need. Since it inherits
QGraphicsItem
I presume setting the group'svisible
property applies to all members of the group, but again you need to check.Really at this point you should check the behaviour for what you want.
-
@JonB I am being asked about my issues status. So time being I am keeping aside parent-child way of implementation. I will try it on my local machine.
Now imagine, in boost-graph, I have created R1 as one vertex. Lines are also treated as vertex. So R1 is connected with 3 vertices , L1,L2 and L3. L2 vertex is connected to R2 vertex etc.....
I have R1 vertex and I have set its _isVisible as false. Through R1 I have iterated to L1, L2 and L3 and made it's visibility as false.
Now the question is , how to tell paint() that R1,L1,L2 and L3 are updated and draw them again.
There, before drawing I will check flag _isVisible and respectively draw it.
How paint() will get QGraphicsItem (R1) ( through R1 I can jump to boost-ptr pointer and then flag and then draw )
I want that QGraphicsItem (R1) in paint(). Is this possible ? -
@tushu
Firstly I really give up at this point. I have no idea how you need to make your Qt items interact with whatever you are doing in your "boost graphics", and I doubt anybody else will either. It really is down to you to try some of this stuff instead of keep asking other people how it might behave, which they won't know.I will say again what has been said by others.
paint()
, on some graphics object, is really not the place to go try alter e.g. the visibility, or anything else, on otherQGraphicsItem
s. The Qt framework callspaint()
on whatever needs updating, according to whatever you have done previously, and its job is just to paint its object. It's not there to play with other objects. For one thing, you have no idea what order objects will have theirpaint()
called; it may have already calledpaint()
on, say, your line items before it callspaint()
on your rectangle, for all you know. You have not respected what we have said about this and keep asking about doing stuff to other items in one item'spaint()
, and that's just not right, keeping asking the same question does not get a different answer. So I'm not going to say that again.I want that QGraphicsItem (R1) in paint(). Is this possible ?
Answered this already multiple times. Doesn't stop you keep asking the same thing. You are already in
R1
svoid myRect::paint(...)
so you have it inthis
.Now the question is , how to tell paint() that R1,L1,L2 and L3 are updated and draw them again.
You don't tell
paint()
items have been updated, items which have been updated causepaint()
to be called. Changing items'visible
value will mark them as updated and cause theirpaint()
s to be called. Do your work on other/all items beforepaint()
is called, whatever causes that to happen on, say, the rectangle do the other items there. Explicitly calling anyQGraphicsItem
'supdate()
method marks it as "dirty"/needing repainting. Also read https://doc.qt.io/qt-5/qgraphicsitem.html#update.That's me done for the best answers I know on this topic.
-
@JonB Really really thanks for your help.
Your 1 line cleared all my doubts.
You are already in R1s void myRect::paint(...) so you have it in this.
The above line cleared my doubt regarding paint().
Now I am able to access boost-graph through its pointer put in QGraphicsItem.
I know, I could not explain properly, and at the end, you were a bit angry. Sorry for that. But I can not explain everything because, if size increases, people tend to avoid such questions.
But anyway sorry, next time I will try to explain properly.
Thank you once again. :) -
@tushu said in Will paint(), redraw everything from scene or will redraw only updated items in Qt?:
You are already in R1s void myRect::paint(...) so you have it in this.
The above line cleared my doubt regarding paint().Not a problem. Explanations can be tricky, especially in non-native languages. But I said that much earlier on in a couple of posts:
paint()
is being called on amyRect
, so that is how it "know, which shape should it draw and its co-ordinates".You showed your
void myRect::paint(...)
. So thatmyRect
,this
, is theQGraphicsItem
being painted. -
From the looks of it, it seems you should go the other way around. Build a simple structure that describes the elements of your graph and in that structure have a pointer to the matching QGraphicsItem that should be handled by it so that when you need to remove it from the graph, you can call hide on the item as well.
Note that I have not used boost's graph library so it's more of a suggestion based on your input.