我有一个QGraphicsScene
和它相关的QGraphicsView
. 我让用户以派生QGraphicsItem
s 的形式在该场景中创建一些形状。我还希望它们可以通过鼠标移动。单击一个或多个项目选择它们,并在按下鼠标按钮的同时移动它们。我继承了 QGraphicsView 来做到这一点,并覆盖mousePressedEvent
, mouseReleasedEvent
&mouseMoveEvent
来实现这一点。当用户单击时,我基本上是在测试一个项目(通过items()
它访问返回关联场景的项目)是否在鼠标下方contains()
,如果是,那么我正在选择它。
在 中mouseMoveEvent
,我setPos()
在选择的每个项目上使用以将其相对于鼠标移动进行移动。它按预期工作和显示。
这可能不是最有效的方法,但这就是我在发现 Qt 时所取得的成就。现在,问题是:一旦我用鼠标移动了我的项目或项目组,如果我想取消选择它们(通过再次单击它们),contains()
提供输入位置的方法就像该项目是没动。示例:我在左上角绘制一个矩形,然后将其移动到视图的中心。再次单击它不起作用,但单击它最初起作用的位置。所以我怀疑它与本地和全球坐标有关。
我今天遇到了几个问题(大部分都解决了),但我被困在这个问题上。
这是我的视图类:
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
场景矩形设置为 (0;0),因此无需担心移动它或其他什么。