我有一个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_()
答案 0 :(得分:4)
我看到你已回答了自己的问题。不过我想解释一下为什么。
每个QGraphicsItem
都有自己的本地坐标系。所以当你这样做时
self.rect = QRectF(position.x(), position.y(), 15, 15)
您基本上从项目的本地坐标系的(0, 0)
开始,然后转到您从x
获取的给定y
和position
。这基本上意味着您的矩形将在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
是QGraphicsItem
中居住的scene
。
答案 1 :(得分:1)
更改
self.rect = QRectF(position.x(), position.y(), 15, 15)
到
self.rect = QRectF(0, 0, 15, 15)
解决了问题