Reputation: 677
I am trying to create my own graphicsitem with a circle and its label at the center.
class circle(QGraphicsItem):
def __init__(self, radius=None, name=None, x=None, y=None, parent=None):
super(circle, self).__init__(parent)
self.radius = radius if radius else random.random()*500
self.label = name if name else "cirA"
self.x = x if x else random.randint(0, 900)
self.y = y if y else random.randint(0, 600)
# self.center = complex(self.x, self.y)
def boundingRect(self):
penWidth = 1.0
return QRectF(-self.x - penWidth / 2, -self.y - penWidth / 2,
self.x + penWidth, self.y + penWidth)
def paint(self, painter, option, widget):
painter.drawEllipse(0, 0, self.radius, self.radius)
painter.drawText(self.label)
Now in my main gui, a list of a circles is held as circleList and I am trying to add the circle item as
for cir in self.circleList:
self.painter.addItem(cir)
but this returns
RuntimeError: wrapped C/C++ object of type circle has been deleted
help?
this should do the trick for the minimal reproduce able example
note: FBS is required and project should be started using
fbs startproject
the circle is also to be added along with the following
from fbs_runtime.application_context.PyQt5 import ApplicationContext
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class gui(QDialog):
def __init__(self, parent=None):
super(gui, self).__init__(parent)
self.painter = QGraphicsScene(10, 10, 900, 600)
self.canvas = QGraphicsView(self.painter)
mainLayout = QGridLayout()
mainLayout.addWidget(self.canvas, 0, 0, 6, 2)
self.setLayout(mainLayout)
self.circleList = []
def drawCircle(self):
pen = QPen(Qt.black, 2, Qt.SolidLine)
self.painter.clear()
for cir in self.circleList:
self.painter.addItem(cir)
self.painter.update()
self.canvas.update()
self.update()
def newCircle(self, cir):
self.circleList.append(cir)
self.drawCircle()
def addCircle(self):
return self.newCircle(circle())
if __name__ == "__main__":
app = ApplicationContext()
test = gui()
test.show()
exit(app.app.exec_())
Upvotes: 0
Views: 3485
Reputation: 244202
Graphics View Framework does not need you to remove and add the items. In your case, when using clear(), you are removing the items from the scene and you are removing them from the memory, so circleList will have variables that no longer have allocated memory.
On the other hand if you want a custom QGraphicsItem that draws a circle and a text in the center then the boundingRect must have the size of the rectangle ex-inscribed to the circle.
Considering the above, the solution is as follows:
class Circle(QGraphicsItem):
def __init__(self, radius=None, name="", x=0, y=0, parent=None):
super(Circle, self).__init__(parent)
self.radius = radius or random.random() * 500
self.label = name if name else "cirA"
self.setPos(x or random.randint(0, 900), y or random.randint(0, 900))
def boundingRect(self):
return QRectF(0, 0, self.radius, self.radius)
def paint(self, painter, option, widget):
painter.drawEllipse(0, 0, self.radius, self.radius)
painter.drawText(0, 0, self.radius, self.radius, Qt.AlignCenter, self.label)
class Gui(QDialog):
def __init__(self, parent=None):
super(Gui, self).__init__(parent)
self.painter = QGraphicsScene(10, 10, 900, 600)
self.canvas = QGraphicsView(self.painter)
mainLayout = QGridLayout(self)
mainLayout.addWidget(self.canvas)
@property
def circleList(self):
return [item for item in self.painter.items() if isinstance(item, Circle)]
def newCircle(self, cir):
self.painter.addItem(cir)
return cir
def addCircle(self):
return self.newCircle(Circle())
Upvotes: 1