【问题标题】:PyQt: QGraphicsItem added at a wrong positionPyQt:QGraphicsItem 添加在错误的位置
【发布时间】:2016-03-01 04:41:04
【问题描述】:

我有一个 QGraphicsItem 的子类,我想在“Control+LMB click”上将它的实例添加到场景中。问题是该项目被添加到坐标比它们应该大两倍的位置。同时使用 scene.addEllipse(...) 添加椭圆效果很好。

#!/usr/bin/env python

import sys
from PyQt4.QtCore import (QPointF, QRectF, Qt, )
from PyQt4.QtGui import (QApplication, QMainWindow, QGraphicsItem, 
                         QGraphicsScene, QGraphicsView, QPen, QStyle)

MapSize = (512, 512)

class DraggableMark(QGraphicsItem):
    def __init__(self, position, scene):
        super(DraggableMark, self).__init__(None, scene)
        self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable)
        self.rect = QRectF(position.x(), position.y(), 15, 15)
        self.setPos(position)
        scene.clearSelection()

    def boundingRect(self):
        return self.rect

    def paint(self, painter, option, widget):
        pen = QPen(Qt.SolidLine)
        pen.setColor(Qt.black)
        pen.setWidth(1)
        if option.state & QStyle.State_Selected:
            pen.setColor(Qt.blue)
        painter.setPen(pen)
        painter.drawEllipse(self.rect)


class GraphicsScene(QGraphicsScene):
    def __init__(self, parent=None):
        super(GraphicsScene, self).__init__(parent)
        self.setSceneRect(0, 0, *MapSize)

    def mousePressEvent(self, event):
        super(GraphicsScene, self).mousePressEvent(event)
        if event.button() != Qt.LeftButton:
            return

        modifiers = QApplication.keyboardModifiers()
        pos = event.scenePos()
        if modifiers == Qt.ControlModifier:
            print("Control + Click: (%d, %d)" % (pos.x(), pos.y()))
            DraggableMark(pos, self)
            self.addEllipse(QRectF(pos.x(), pos.y(), 10, 10))
        else:
            print("Click: (%d, %d)" % (pos.x(), pos.y()))


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.scene = GraphicsScene(self)
        self.scene.addRect(QRectF(0, 0, *MapSize), Qt.red)
        self.view = QGraphicsView()
        self.view.setScene(self.scene)
        self.view.resize(self.scene.width(), self.scene.height())
        self.setCentralWidget(self.view)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    rect = QApplication.desktop().availableGeometry()
    window.resize(int(rect.width()), int(rect.height()))
    window.show()
    app.exec_()

【问题讨论】:

    标签: pyqt qgraphicsitem


    【解决方案1】:

    我看到你已经回答了你自己的问题。不过,我想解释一下为什么这是有效的。

    每个QGraphicsItem 都有自己的局部坐标系。所以当你这样做时

    self.rect = QRectF(position.x(), position.y(), 15, 15)
    

    您基本上从项目本地坐标系的(0, 0) 开始,然后转到您从position 获取的给定xy。这基本上意味着您的矩形将在 position.x() + position.x()position.y() + position.y() 绘制,第一个 position.x()/position.y() 是场景中 QGraphicsItem 的位置,第二个 position.x()/position.y() 是在项目的本地坐标系内定位。

    如果你想从QGraphicsItem的起源开始,你必须使用

     self.rect = QRectF(0, 0, 15, 15)
    

    这确保您从本地坐标系的原点开始。

    这个问题特别棘手,因为默认情况下对象被添加到场景的(0, 0)。所以position.x() + position.x()position.y() + position.y() 在这种情况下实际上不会显示手头的问题,因为0+0 总是等于0。当您将默认位置更改为其他位置时,就会出现问题。

    这是一个 3D 图,可视化了我上面描述的内容(我找不到 2D 示例,但原理是相同的:P):

    这里的world 是场景,而object 是驻留在scene 中的QGraphicsItem

    【讨论】:

      【解决方案2】:

      变化

      self.rect = QRectF(position.x(), position.y(), 15, 15)
      

      self.rect = QRectF(0, 0, 15, 15)
      

      解决了问题

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多