【问题标题】:Converting points between coordinates of two QGraphicsItem's in a scene在场景中两个 QGraphicsItem 的坐标之间转换点
【发布时间】:2019-09-05 12:21:30
【问题描述】:

我在将一个项目的坐标中的点转换为另一项目的坐标时遇到困难,就像这样

from PySide import QtGui, QtCore
import sys

class Editor(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Editor, self).__init__(parent)

        scene = QtGui.QGraphicsScene()

        line0 = QtGui.QGraphicsLineItem(  10 , 210 ,  10 , 300 )
        line1 = QtGui.QGraphicsLineItem( 100 , 210 , 100 , 300 )

        scene.addItem( line0 )
        scene.addItem( line1 )

        view = QtGui.QGraphicsView()
        view.setScene( scene )

        self.setGeometry( 250 , 250 , 600 , 600 )
        self.setCentralWidget(view)
        self.show()

        print line1.mapToItem( line0 , QtCore.QPoint( 0 , 0 ) )  # QPoint( 0 , 0 ) in line0's coordinates -> line1's coordinates
        print line1.mapToScene( QtCore.QPointF( 0 , 0 ) )        # QPoint( 0 , 0 ) in line0's coordinates -> screen coordinates


if __name__=="__main__":
    app=QtGui.QApplication(sys.argv)
    myapp = Editor()
    sys.exit(app.exec_())

结果似乎表明转换失败

PySide.QtCore.QPointF(0.000000, 0.000000)
PySide.QtCore.QPointF(0.000000, 0.000000)

【问题讨论】:

  • 什么是PySide?这是你做的课吗?
  • 它是 Qt Python binding
  • @Olumide 你打算得到什么?,我看是对的
  • @eyllanesc 我期待看到 line1 wrt line0 的坐标,例如( -90 , 0)
  • @Olumide 好的,那是 line1.mapToItem(line0, ... 和其他情况?

标签: python pyside qgraphicsview qgraphicsscene qgraphicsitem


【解决方案1】:

我认为您假设项目的坐标系从其 topLeft boundingRect 开始,但事实并非如此。此外,另一个概念是您传递给 QGraphicsLineItem 构造函数的坐标是相对于该项目的,而不是相对于场景的坐标。

p1(x1, y1)
    ╲
     ╲
      ╲
       ╲
        ╲
         ╲
        p2(x2, y2)
The coordinates (x1, y1) and (x2, y2) are relative to the QGraphicsLineItem

因此,如果您想获得两条线之间相对于 line1 的位置差异,您必须映射与 QGraphicsLineItem 关联的 QLineF 的 p1() 的值:

print(line1.mapToItem(line0 , line0.line().p1()) -   line1.line().p1())
      └----p1 that belongs to line0 ----------┘    └--p1 that belongs--┘    
              with respect to line1            to line1 with respect to line1

输出:

PySide.QtCore.QPointF(-90.000000, 0.000000)

说明:

Graphics View Framework 处理 3 种坐标系:

  • 关于 QGraphicsView 的视口的坐标,即坐标取决于视图
  • 相对于场景的坐标系,所有视图都具有相同的坐标系。
  • 每个项目的坐标系

可以用图像或视频记录系统进行类比。第一个坐标系指的是相对于相机可以看到的内容,这取决于类似于 QGraphicsView 的每个相机。第二个坐标系是相对于现实世界的,它不依赖于相机。第三个坐标系是相对于场景中的一个元素,例如一个演员

项目坐标系的点(0, 0)与场景中项目的位置相匹配。在您的情况下,您的项目相对于场景的位置是 (0, 0)(使用 print(line0.pos() 检查)。

从视觉上理解下面的代码是相同的,但在概念上是不同的。

class Editor(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(Editor, self).__init__(parent)
        scene = QtGui.QGraphicsScene()
        line0 = QtGui.QGraphicsLineItem(0, 0, 0, 90)
        line0.setPos(10, 210)
        line1 = QtGui.QGraphicsLineItem(0, 0, 0, 90)
        line1.setPos(100, 210)
        scene.addItem( line0 )
        scene.addItem( line1 )
        view = QtGui.QGraphicsView()
        view.setScene( scene )
        self.setGeometry( 250 , 250 , 600 , 600 )
        self.setCentralWidget(view)
        self.show()

【讨论】:

  • 结果与line0.line().p1() - line1.line().p1()相同! ...让我想知道是否存在相对坐标系统是传递给QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value)value 总是 相对于项目的初始位置。我真正想要做的是防止 RHS 上的行项目被拖过 LHS 上的行项目。因此,根据订单项的相对偏移量进行推理会简单得多。
  • @Olumide 在这种情况下它是一致的,因为项目相对于场景的位置(line0.pos() == line1.pos() == QtCore.QPointF(0, 0))是相同的,但在一般情况下不存在。另一方面,从 itemChange 获得的位置是项目相对于场景的位置。我认为你有一个 XY 问题,你的最终目标是什么?您是否希望 QGraphicsLineItem 的分离不超过阈值?以及测量坐标系的阈值?
  • @Olumide [cont.] 目前,您的示例很简单,因为它没有缩放、旋转等转换。我建议阅读 doc.qt.io/qt-5/graphicsview.html 以了解坐标系
  • 感谢您的解释。行项目之间的行为/关系与拆分器的句柄没有什么不同。所以也许我应该看看我能用分离器走多远。 (我开始产生这样一种感觉,即 Qt 中的复杂解决方案通常会重新发明 Qt 已经拥有的某种功能。Qt 是一个非常古老而庞大的框架,它很有可能实现了用户可能需要的大多数 UI 功能和行为.)
  • 如果你愿意,我愿意chat
猜你喜欢
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-14
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
  • 2011-05-09
相关资源
最近更新 更多