2

QGraphicsItem のサブクラスがあり、そのインスタンスを「Control + LMB クリック」でシーンに追加したいと考えています。問題は、本来の 2 倍の座標の位置にアイテムが追加されることです。同時に、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_()
4

2 に答える 2

6

あなた自身の質問に答えているようです。しかし、なぜこれが機能するのかを説明したいと思います。

すべてQGraphicsItemに独自のローカル座標系があります。だからあなたがするとき

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

基本的(0, 0)に、アイテムのローカル座標系の から開始し、 から取得した指定された および に移動xyますpositionposition.x() + position.x()これは基本的にposition.y() + position.y()、最初のposition.x()/position.y()QGraphicsItemシーン内の位置で、2 番目のposition.x()/position.y()がアイテムのローカル座標系内の位置で描画されることを意味します。

の原点から開始したい場合はQGraphicsItem、使用する必要があります

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

これにより、ローカル座標系の原点から開始することが保証されます。

この問題は、デフォルトでオブジェクトが(0, 0)シーンに追加されるため、特に注意が必要です。したがってposition.x() + position.x()、この場合、は常に に等しいためposition.y() + position.y()、実際には目前の問題は表示されません。問題が発生するのは、デフォルトの位置を別のものに変更した瞬間です。0+00

上記で説明したことを視覚化した 3D 図を次に示します (2D の例を見つけることができませんでしたが、原理は同じです:P):

ここに画像の説明を入力

はそこに住んでいるのworldに対し、ここはシーンです。objectQGraphicsItemscene

于 2016-02-28T20:22:47.870 に答える
1

変化

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

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

問題を解決しました

于 2013-10-02T09:21:47.920 に答える