在QGraphicsScene中通过鼠标移动QGraphicsItem

时间:2013-10-29 20:12:42

标签: qt pyqt qt5 qgraphicsview qgraphicsscene

我有一个QGraphicsScene及其关联的QGraphicsView。我让用户以派生QGraphicsItem的形式创建一些形状到那个场景中。我也希望它们可以通过鼠标移动。单击一个或多个项目选择它们,并在按下鼠标按钮时移动它们。我继承了QGraphicsView来执行此操作,并覆盖了mousePressedEventmouseReleasedEvent& 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),所以不用担心移动它或其他什么。

0 个答案:

没有答案