QGraphicsItemGroup的翻译在销毁后在哪里发送?

问题描述 投票:1回答:1

根据QGraphicsItem,在我使用QGraphicsItemGroup共同移动的场景中有this answer个对象。

虽然组还活着,但它保持自己的变换。现在,一旦销毁这些转换,它们便不复存在,必须派遣出去。我的问题是如何完成,特别是在翻译方面。

我举了一个小例子,其中显示一个矩形,然后在5秒钟的暂停后缩放并平移。在每个步骤之后显示对象的转换。

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_())

它打印以下内容:

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

因此,我们从一个恒等变换矩阵开始,在缩放后将其更改为缩放矩阵以保存缩放因子。

但是,在平移之后,尽管矩形确实已经移动,变换矩阵也没有改变。

所以我的问题是,该小组的翻译被销毁后会在哪里派发?

python pyqt pyqt5 qgraphicsitemgroup
1个回答
1
投票

首先,不要使用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
QObject::startTimer: Timers cannot be started from another thread
QObject::startTimer: Timers cannot be started from another thread
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
QObject::startTimer: Timers cannot be started from another thread
QObject::startTimer: Timers cannot be started from another thread
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移动了该项。

© www.soinside.com 2019 - 2024. All rights reserved.