I'm trying to remove a QGraphicsItem from a QGraphicsItemGroup. When calling removeFromGroup, the item is removed (of course). However, it's then no longer visible in the Scene. I have to call Scene.addItem(item) in order for it to appear again. This is apparently something you shouldn't do (I'm given a warning for doing that). But I can't seem to find another workaround.
Here's a minimal example:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.view = QGraphicsView()
self.scene = QGraphicsScene()
self.view.setScene(self.scene)
self.setCentralWidget(self.view)
def add_group(scene):
group = QGraphicsItemGroup()
text = QGraphicsTextItem()
text.setPlainText("I'm visible")
group.addToGroup(text)
scene.addItem(group)
# After this, text is no longer in group. However, it is no longer visible.
group.removeFromGroup(text)
assert not text in group.childItems()
# But text is still in scene.
assert text.scene() == scene
# this works (i.e. text becomes visible again). However, it also produces a
# warning: QGraphicsScene::addItem: item has already been added to this scene.
# The docs also advice against it.
scene.addItem(text)
# According to the docs, I thought this might work, but it gives me a TypeError.
# text.setParentItem(0)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
add_group(main.scene)
main.show()
sys.exit(app.exec_())
Tips and hints are very welcome.
The QGraphicsTextItem can never be parented to a scene, because it's parent must be a QGraphicsItem (which QGraphicsScene does not inherit).
When the QGraphicsTextItem is created, it's parent is None
. Its parent is set to group
when it is added to it (QGraphicsItemGroup is a subclass of QGraphicsItem), then set back to None
when it's removed from group
.
Calling scene.addItem()
is actually a NO-OP. Qt checks whether scene
is the same as text.scene()
, and if it is, it prints the warning and returns without doing anything.
The fact that it seems to "work" in some circumstances, is just an artifact of python's garbage-collecting mechanism.
If your test is re-cast in a more realistic way, the QGraphicsTextItem remains visible after removal from the group:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.view = QGraphicsView(self)
self.scene = QGraphicsScene(self.view)
self.view.setScene(self.scene)
self.setCentralWidget(self.view)
self.group = QGraphicsItemGroup()
self.text = QGraphicsTextItem()
self.text.setPlainText("I'm visible")
self.group.addToGroup(self.text)
self.scene.addItem(self.group)
self.group.removeFromGroup(self.text)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())