Solved polygon QGraphicsItem shape
-
Not sure this is related to your issue, but is there any specific reason you flip the y axis?
-
@Asperamanca
what do you mean by flip? for bounding rect i take top left and bottom right coordinates of the rect -
@user4592357
GraphicItem coordinates are origin at top left and positive axis down to the right. So your Y axis is flipped.
Unless you changed it somewhere else. -
@kenchan
oh right, so i need to take bottom left and top right points? -
@user4592357
no, top left and bottom right is probably what you needQRectF(QPointF(min_x, min_y), QPointF(max_x, max_y))
-
@kenchan
that's what i was saying -
@user4592357
:-) -
@user4592357 said in polygon QGraphicsItem shape:
Not sure that came across:
The way you posted your code, you actually use bottom/left and top/right to construct the rectangle.return QRectF(QPointF(min_x, max_y), QPointF(max_x, min_y))
-
@kenchan
it's really weird. i set background brush to black of my graphics view, and when i add something likeitem = PolygonItem([QPointF(30, 30), QPointF(50, 50), QPointF(100, 100)])
to the scene, the view becomes white and no item is drawn :(
here's the scene and view:
class Scene(QGraphicsScene): def __init__(self, parent=None): super(Scene, self).__init__(parent) class View(QGraphicsView): def __init__(self, parent=None): super(View, self).__init__(parent) self.setRenderHint(QPainter.Antialiasing) self.setRenderHint(QPainter.TextAntialiasing) self.setSceneRect(self.scene().sceneRect()) self.setBackgroundBrush(QBrush(Qt.black))
this is how i create the scene and view in main window:
def __create_scene_and_view(self): self.__scene = Scene(self) self.__view = View(self.__scene) self.__layout_view.show() self.setCentralWidget(self.__view)
some items are drawn correctly, though. for example:
item = PolygonItem([QPointF(75, -10), QPointF(60, 40), QPointF(110, 10), QPointF(0, 0)])
i noticed, if i add
QPointf(0, 0)
to the first (non-working) item, it is drawn too -
@kenchan
hi,i fixed the above issue (related to bounding box)
this is the bound rect now:
bb = brect(self.coords) if self._hovered: bb.setX(bb.x() - 4) bb.setY(bb.y() - 4) bb.setWidth(bb.width() + 4) bb.setHeight(bb.height() + 4) return bb
and this is paint():
def paint(self, painter, option, widget): pen_outline = QPen(QBrush(QColor(Qt.cyan)), 5, join=Qt.MiterJoin) pen_line = QPen(QBrush(QColor(Qt.red)), 3, join=Qt.MiterJoin) if self._hovered: painter.setPen(pen_outline) painter.drawPolygon(QPolygonF(self.coords)) painter.setPen(pen_line) painter.drawPolygon(QPolygonF(self.coords))
and these are the results when normal:
and when hovering:
as you can see, the red rectangle has become a lot thicker. why is that?
i think one reason may be that i'm using coordinates for both normal and highlighted drawing?
by the way, if i remove the
if
in bounding rect, i get the "outline" drawn, only within the rect but i need outside it. -
@user4592357 Hello again,
I can't see why the red box should get thicker with that code.
You should probably only offset your bounding box position by -2 if you increase the width and height by 4 (4/2=2 extra pixels on each side). -
@kenchan
i have played with numbers. setting that to -2 looks worseif i remove the if in bounding rect, i get the "outline" drawn, only within the rect but i need outside it.
-
@user4592357
since you have a width of 3 and 5. assuming the thicker red line in the lower image is width 3 the cyan line looks correct at width 5 having 1 pixel on each side. So, I am thinking that the upper thinner rectangle is incorrectly drawn. It does not look like it has a width of 3 to me. I cannot see why that is though.
BTW it made a similar one with C++ and it looks fine. -
@kenchan
red is probably 3, because cyan is 5. but i remove theif
fromboundingRect()
now, when both are drawn from same (x, y), since cyan is 5, is appears to be inside the rect.
when i do this, however, the item "goes up" everytime it is hovered:def paint(self, painter, option, widget): # create the pens pen_outline = QPen(QBrush(QColor(Qt.cyan)), 5, join=Qt.MiterJoin) pen = QPen(QBrush(QColor(Qt.red)), 3, join=Qt.MiterJoin) if self._hovered: painter.setPen(pen_outline) coords = [] for coord in self.coords: coord.setX(coord.x() - 2) coord.setY(coord.y() - 2) coords.append(coord) painter.drawPolygon(QPolygonF(coords)) painter.setPen(pen) painter.drawPolygon(QPolygonF(self.coords))
i need to do something like this i guess - draw a bigger polygon under the original one.
but how can i do it, having the coordinates? -
your bounding rect should have either the small rect (when not hovering) or the large rect (when hovering). It might work fine with only the large rect though.
My bounding rect looks like this, it works fine.QRectF TestItem2::boundingRect() const { if(hovering) return QRectF(-2, -2, 104, 104); else return QRectF(-1,-1, 102, 102); }
my paint function looks like this
void TestItem2::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QPen pen5(QBrush(QColor(0,255,255)),5,Qt::SolidLine,Qt::SquareCap,Qt::MiterJoin); QPen pen3(QBrush(QColor(255,0,0)),3,Qt::SolidLine,Qt::SquareCap,Qt::MiterJoin); const QPointF points[4] = {QPointF(0.0,0.0),QPointF(100.0,0.0),QPointF(100.0,100.0),QPointF(0.0,100.0)}; if(hovering) { painter->setPen(pen5); painter->drawPolygon(points,4); } painter->setPen(pen3); painter->drawPolygon(points,4); }
not quite the same as yours but close enough.
I see you have QGraphicsItem.ItemClipsToShape set, that might cause you problems if you don't have your shape function working correctly. Assuming you do have a shape function defined that is.
-
@kenchan
yeah it was that... ugh, thanks.by the way how can i make the outline don't appear "inside"?
-
@user4592357
You want the highlight outline not to show inside the red box? -
@kenchan
yes -
@user4592357
hmm. easiest way with a simple rectangle is to just draw a line of width 1 around the outside of your red one.
Same thing if it is more complex polygon but tricky to offset the points in the correct direction.
-
@kenchan
that's actually what i wanted to do - but the problem is i don't know when to add and when to subtract from coordinate:def paint(self, painter, option, widget): """ Mandatory override of base class. """ # create the pens pen_outline = QPen(QBrush(QColor(Qt.cyan)), 1, join=Qt.MiterJoin) pen = QPen(QBrush(QColor(Qt.red)), 2, join=Qt.MiterJoin) if self._hovered: painter.setPen(pen_outline) for pt in range(len(self.coords)): coord1 = self.coords[pt % len(self.coords)] - QPointF(1, 1) coord2 = self.coords[(pt + 1) % len(self.coords)] - QPointF(1, 1) painter.drawLine(coord1, coord2) # painter.drawPolygon(QPolygonF(self.coords)) painter.setPen(pen) painter.drawPolygon(QPolygonF(self.coords))
result: