2

我有一个QGraphicsScene和它相关的QGraphicsView. 我让用户以派生QGraphicsItems 的形式在该场景中创建一些形状。我还希望它们可以通过鼠标移动。单击一个或多个项目选择它们,并在按下鼠标按钮的同时移动它们。我继承了 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),因此无需担心移动它或其他什么。

4

0 回答 0