Прежде всего, не используйте QThread + sleep для задержки, так как у вас могут быть странные поведения, Qt предупреждает вас, указывая на предупреждение на консоли:
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
<b>QObject::startTimer: Timers cannot be started from another thread
QObject::startTimer: Timers cannot be started from another thread</b>
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
<b>QObject::startTimer: Timers cannot be started from another thread
QObject::startTimer: Timers cannot be started from another thread</b>
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
Вместо этого используйте QTimer.
Переходя к задаче, давайте проанализируем положение элемента по мере применения изменений:
from PyQt5.QtCore import Qt, QObject, QTimer
from PyQt5.QtGui import QTransform
from PyQt5.QtWidgets import (
QApplication,
QGraphicsRectItem,
QGraphicsScene,
QGraphicsView,
QMainWindow,
)
import sys
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 Test(QObject):
def initial(self):
print(rect.pos())
print("initial transforms")
print_transforms(rect)
QTimer.singleShot(5000, self.scaling)
def scaling(self):
print(rect.pos())
group = scene.createItemGroup([rect])
group.setTransform(QTransform().scale(1.5, 1.5))
scene.destroyItemGroup(group)
print("after scaling")
print_transforms(rect)
QTimer.singleShot(5000, self.translation)
print(rect.pos())
def translation(self):
print(rect.pos())
group = scene.createItemGroup([rect])
group.setTransform(QTransform().translate(100.0, 100.0))
print(rect.pos())
scene.destroyItemGroup(group)
print("after translation")
print_transforms(rect)
print(rect.pos())
QTimer.singleShot(1000, QApplication.quit)
if __name__ == "__main__":
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()
test = Test()
test.initial()
sys.exit(app.exec_())
И вы получите следующее:
PyQt5.QtCore.QPointF()
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
PyQt5.QtCore.QPointF()
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
PyQt5.QtCore.QPointF()
PyQt5.QtCore.QPointF()
PyQt5.QtCore.QPointF()
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
PyQt5.QtCore.QPointF(100.0, 100.0)
Где видно, что перевод применяется к позиции элемента, а не к QTransform
, поскольку при использовании destroyItemGroup()
это означает:
void QGraphicsScene :: destroyItemGroup ( QGraphicsItemGroup * group)
Переопределяет все элементы в группе в родительский элемент группы, затем удаляет группу со сцены и, наконец, удаляет ее. Позиции и трансформации предметов отображаются из группы в родительскую группу.
(выделено мной)
В заключение: Когда группа уничтожается, все преобразования передаются элементам, кроме перевода, поскольку элемент перемещается с помощью setPos.