# Drawing a custom arbitrary shape (ellipse/polygon)

• Hello,

I am trying to make a QGraphicsItem draw a polygon based on a custom class:

``````class Shape:

shapes = {
'square': [(-4, -4), (4, -4), (4, 4), (-4, 4)],
'triangle': [(0, -4), (4, 4), (-4, 4)],
'star': [(-1, -1), (0, -6), (1, -1), (5, 4), (0, 1), (-5, 4), (-1, -1)],
'x': [(0, -2), (3, -5), (5, -3), (2, 0), (5, 3),
(3, 5), (0, 2), (-3, 5), (-5, 3), (-2, 0), (-5, -3), (-3, -5)]
}

def __init__(self, name):
self.name = name
self._scale = 1
self._shape = self.build_shape(self.name)

def build_shape(self, shape_name):
# Build QPolygon dictionary from Shapes coordinates
shape = QPolygon([QPoint(*point) * self.scale
for point in Shape.shapes[shape_name]])
return shape

@property
def name(self):
return self._name

@name.setter
def name(self, value):
if value not in self.shapes.keys():
e = f'Invalid Shape name: "{value}" '
e += f'(valid Shapes are: {list(self.shapes.keys())})'
raise ValueError(e)
self._name = value

# No setter as this is read-only
@property
def shape(self):
return self._shape

@property
def scale(self):
return self._scale

@scale.setter
def scale(self, value: float):
if not 0.5 <= value <= 3:
e = f'Invalid Shape scale: {value} '
e += f'(valid Shape scale range is 0.5 to 3)'
raise ValueError(e)
else:
self._scale = value
# Rebuild the shape with the new scale factor
self._shape = self.build_shape(self.name)
``````

I can then do a `drawPolygon(shape)` in my QGraphicsItem-derived class.

Now, I would like to use a default circle if no shape name is provided, but I do not want to do it inside the QGraphicsItem class, like this:

``````        if shape.name == 'circle':
painter.drawEllipse(-2, -2, 4, 4)
else:
painter.drawPolygon(shape.shape)
``````

Rather, I would like this behavior to be set up in the Shape class, which would return either an ellipse or a polygon, to be drawn later inside QGraphicsItem. If the default shape needs to be changed later, I'd like to be able to do it from within the Shape class, and not anywhere else.

I can't find a way to return something like a QEllipse (which doesn't exist). Is there a QPainter method which can accept either an ellipse or a polygon, and draw either?

Thanks.

• Hi,

The simplest would be to pass the painter to your helper class and let it do the correct call.

Add a draw method for that.

• @SGaist Thanks a lot. I thought about that, but then I realised I would be much better off doing all of this with Unicode symbols instead of drawing vector shapes, which has simpified everything greatly :)