我有一个QGraphicsScene
及其关联的QGraphicsView
。我让用户以派生QGraphicsItem
的形式创建一些形状到那个场景中。我也希望它们可以通过鼠标移动。单击一个或多个项目选择它们,并在按下鼠标按钮时移动它们。我继承了QGraphicsView来执行此操作,并覆盖了mousePressedEvent
,mouseReleasedEvent
& mouseMoveEvent
实现这一目标。当用户点击时,我基本上测试一个项目(通过items()
访问,返回相关场景的项目)是否在contains()
的鼠标下,如果是,那么我正在选择它。
在mouseMoveEvent
中,我在选项的每个项目上使用setPos()
将其相对移动到鼠标移动。它按预期工作和显示。
这可能不是最有效的方式,但这是我在发现Qt时所取得的成就。现在,问题是:一旦我用鼠标移动了我的项目或项目组,如果我想取消选择它们(通过再次点击它们),提供输入行为位置的contains()
方法就好像物品没有移动一样。示例:我在左上角绘制一个矩形,然后将其移动到视图的中心。再次单击它不会,但会点击它最初的工作位置。所以我怀疑它与局部坐标和全局坐标有关。
我今天遇到了几个问题(大多数问题已经解决了),但我仍然坚持这个问题。
这是我的View类:
class CustomGraphicsView(QGraphicsView):
def __init__(self, *args):
super().__init__(*args)
self.selection = []
self.offsets = []
self.select_point = None
def mousePressEvent(self, event):
pos = self.mapFromGlobal(event.globalPos())
modifiers = event.modifiers()
if event.button() == Qt.LeftButton:
#do something else
elif event.button() == Qt.RightButton:
self.select_point = pos
for s in self.selection:
if s.contains(pos): # deselect or drag
for s in self.selection: # construct the offsets for dragging
self.offsets = [s.pos() - pos for s in self.selection]
break
def mouseReleaseEvent(self, event):
pos = self.mapFromGlobal(event.globalPos())
modifiers = event.modifiers()
if event.button() == Qt.LeftButton:
#do something else
elif event.button() == Qt.RightButton:
if self.select_point == pos: # one click selection
self.update_selection(pos)
if self.offsets:
self.offsets.clear()
def mouseMoveEvent(self, event):
pos = self.mapFromGlobal(event.globalPos())
modifiers = event.modifiers()
if event.buttons() == Qt.RightButton:
if not self.offsets:
for s in self.selection:
self.offsets = [s.pos() - pos for s in self.selection]
for s, off in zip(self.selection, self.offsets):
s.set_pos(pos + off)
def update_selection(self, pos):
for item in self.items():
if not item.contains(pos):
continue
if item.selected:
self.selection.remove(item)
else:
self.selection.append(item)
item.select()
break
场景rect设置为(0; 0),所以不用担心移动它或其他什么。