I have QGraphicsItem
objects in a scene that I move jointly using a QGraphicsItemGroup
, as per this answer.
While the group is alive, it keeps its own transforms. Now once it is destroyed, these transforms cease to exist, and must be dispatched. My question is how is it done — in particular for the translation.
I have made a small example where a rectangle is displayed, then scaled and translated after pauses of 5 seconds. The object's transformations are displayed after each step.
from PyQt5.QtCore import Qt, QThread
from PyQt5.QtGui import QTransform
from PyQt5.QtWidgets import QApplication, QGraphicsRectItem, QGraphicsScene, QGraphicsView, QMainWindow
import sys
import time
def print_transforms(obj):
t = obj.transform()
print(t.m11(), t.m12(), t.m13(), t.m21(), t.m22(), t.m23(), t.m31(), t.m32(), t.m33(), t.dx(), t.dy())
assert len(obj.transformations()) == 0
print(obj.rotation(), obj.scale())
class Thread(QThread):
def run(self):
print('initial transforms')
print_transforms(rect)
time.sleep(5)
group = scene.createItemGroup([rect])
group.setTransform(QTransform().scale(1.5, 1.5))
scene.destroyItemGroup(group)
print('after scaling')
print_transforms(rect)
time.sleep(5)
group = scene.createItemGroup([rect])
group.setTransform(QTransform().translate(100., 100.))
scene.destroyItemGroup(group)
print('after translation')
print_transforms(rect)
time.sleep(5)
app = QApplication([])
window = QMainWindow()
window.setGeometry(100, 100, 400, 400)
view = QGraphicsView()
scene = QGraphicsScene()
view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
rect = QGraphicsRectItem(0, 0, 150, 150)
scene.addItem(rect)
view.setScene(scene)
window.setCentralWidget(view)
window.show()
thread = Thread()
thread.finished.connect(app.exit)
thread.start()
sys.exit(app.exec_())
It prints the following:
initial transforms
1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0 0.0
0.0 1.0
after scaling
1.5 0.0 0.0 0.0 1.5 0.0 0.0 0.0 1.0 0.0 0.0
0.0 1.0
after translation
1.5 0.0 0.0 0.0 1.5 0.0 0.0 0.0 1.0 0.0 0.0
0.0 1.0
So we start from an identity transform matrix, and after the scaling it is changed to a scaling matrics to hold the scaling factor.
However, after the translation, the transformation matrix is not changed, despite the fact that the rectangle has indeed moved.
So my question is, where is the group's translation dispatched after it has been destroyed?
First of all do not use QThread + sleep to make a delay since you may have strange behaviors, Qt alerts you by pointing to the warning on the console:
Instead use QTimer.
Going to the problem, let's analyze the position of the item as the changes are applied:
And you get the following:
Where it is seen that the translation is applied to the position of the item and not to
QTransform
since when usingdestroyItemGroup()
that indicates:(emphasis mine)
In conclusion: When the group is destroyed, all the transformations are passed to the items except the translation since the item is moved using setPos.