QGraphicsItem bad item drawing
-
I am trying to make a simple item, with some custom painting inside it, but unluckly as always, there are some problems... When i try to reimplement paint, it does work untill i move the item, then the old painting isn't removed, but it still appear on the screen, and this is only in the text area i added.
I tried to look it up, but nothing does fix it... If i try to take widget->update() then yes, it does work, but the performance is crap when i add let's say 1000 of items, the default QGraphicsRectItem works much faster, and i don't understand why that text is not removed.
void Rectangle_Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->drawText(QRect(rect().x(), rect().y() - 12, rect().width(), rect().height()), "NONE"); painter->drawRect(rect()); }
-
Does your code meet the requirement in the first Note of the QGraphicsItem::paint() docs? Where does rect() come from? Does its value change independently?
-
@Loc888 said in QGraphicsItem bad item drawing:
rect().y() - 12
rect.x
/y()
are the top-left coordinates of the rectangle (y()
increases downwards).rect()
(actuallyboundingRect()
which I mention below) is the area being (re-)drawn; you are expected to draw within that rectangle.rect().y() - 12
draws outside the prescribed area. But Qt infrastructure does not know you have done that. I imagine you see that when you move the item downwards it leaves the top 12-odd pixels of the characters ofNONE
as they are, creating that "smear" pattern?@ChrisW67 drew you attention to https://doc.qt.io/qt-5/qgraphicsitem.html#paint:
Make sure to constrain all painting inside the boundaries of
boundingRect()
to avoid rendering artifacts (asQGraphicsView
does not clip the painter for you).You are indeed seeing such "artifacts" [sic.!!]
You should draw within
rect()
. Try removing the- 12
--- does it work OK now?If you do need to draw the text above the rectangle, you need to override QRectF QGraphicsItem::boundingRect() const:
This pure virtual function defines the outer bounds of the item as a rectangle; all painting must be restricted to inside an item's bounding rect. QGraphicsView uses this to determine whether the item requires redrawing.
Reimplement this function to let QGraphicsView determine what parts of the widget, if any, need to be redrawn.You need to expanding the bounding rectangle to encompass all areas you draw into.
-
As @JonB explained in detail, if your "text" (or any other part of your item), is outside the
item
's boundingRect, even when it's just one pixel, it behaves like a brush. So you "paint" with a "None"-shaped (literally) brush on your canvas / background... And it is permanent until this area gets updated again, for example when you move the item's boundingRect over that area.
That's why you only see it, when you drag your item downwards. Because when you drag upwards, the item's boundingRect follows after your "None"-text and clears that area again.So make sure the text is inside the boundingRect of your item or create an extra Textitem and attach it to your rect_item.
-
@ChrisW67 The rect comes from the rect item it self, i didn't read the documentation, since the code was so simplistic, that i didn't find the need to be honest, but i look up similar problems and the solutions for them didn't fix my problem.
-
QRectF Rectangle_Item::boundingRect() const
{
return QRect(rect().x(), rect().y(), rect().width()+15, rect().height()+15);
}At the begining i did -12 in boundingRect but on the x side by mistake..... Then i concluded that the problem must be too small rect, so i increased the size of it as in the code above, but i forgot to correct the y position, the problem is fixed if i add this:
QRectF Rectangle_Item::boundingRect() const
{
return QRect(rect().x(), rect().y() - 13, rect().width()+13, rect().height()+13);
}Nevermind, that's how you endup when you code late morning when you suppose to be sleeping for like few hours.
-
@Loc888
Correct principle. There is no reason forrect().width()+13
. Unless you have altered anything I think you should have:void Rectangle_Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->drawText(QRect(rect().x(), rect().y() - 12, rect().width(), 12 /* altered*/), "NONE"); painter->drawRect(rect()); }
and
QRectF Rectangle_Item::boundingRect() const { return QRect(rect().x(), rect().y() - 13, rect().width() /* altered*/, rect().height()+13); }