PyQt:QGraphicsItem添加在错误的位置

时间:2013-10-01 16:25:11

标签: pyqt qgraphicsitem

我有一个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_()

2 个答案:

答案 0 :(得分:4)

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

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

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

您基本上从项目的本地坐标系的(0, 0)开始,然后转到您从x获取的给定yposition。这基本上意味着您的矩形将在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):

enter image description here

这里是world场景,而objectQGraphicsItem中居住的scene

答案 1 :(得分:1)

更改

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

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

解决了问题