【问题标题】:subclassing QGraphicsView and using mouseMoveEvent and mouseClickEvent messes up moving QGraphicsItems in my scene继承 QGraphicsView 并使用 mouseMoveEvent 和 mouseClickEvent 在我的场景中移动 QGraphicsItems
【发布时间】:2020-06-11 22:02:22
【问题描述】:

Pyside2:我正在继承 QGraphicsView 并向 mouseClickEvent 和 mouseMoveEvent 添加缩放和平移功能。

当我这样做时,我的场景中启用了 Selectable 和 Moveable 的 QGraphicsItem 在第一次单击和拖动后不会正确移动。

它们在第一次单击和拖动时移动良好,但如果我再次单击并拖动它们,它们会重新回到创建它们的位置并从那里移动。

这是我所拥有的:

class ZoomView(QGraphicsView):
    '''
    View class with zoom enabled
    '''
    def __init__(self):
        super(ZoomView, self).__init__()
        self.alt_key = False
        self.ctrl_key = False
        self.mid_button = False
        self.left_button = False

        self.mouse_pos = None
        self.orig_pos = None

        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(2)
        sizePolicy.setHeightForWidth(True)

        self.setSizePolicy(sizePolicy)
        self.setMinimumSize(QtCore.QSize(0, 0))
        self.setRenderHints(QtGui.QPainter.Antialiasing | QtGui.QPainter.TextAntialiasing)

        self.setResizeAnchor(QGraphicsView.NoAnchor)
        self.setObjectName("PickerView")
        self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)

        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Alt:
            self.alt_key = True
        elif event.key() == QtCore.Qt.Key_Control:
            self.ctrl_key = True
        else:
            return super(ZoomView, self).keyPressEvent(event)

    def keyReleaseEvent(self, event):
        if event.key() == QtCore.Qt.Key_Alt:
            self.alt_key = False
        elif event.key() == QtCore.Qt.Key_Control:
            self.ctrl_key = False
        else:
            return super(ZoomView, self).keyReleaseEvent(event)

    def mousePressEvent(self, event):

        self.mouse_pos = event.pos()
        if event.button() == QtCore.Qt.MidButton:
            self.mid_button = True

        if event.button() == QtCore.Qt.LeftButton:
            super(ZoomView, self).mousePressEvent(event)
            self.left_button = True

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.MidButton:
            self.mid_button = False
        elif event.button() == QtCore.Qt.LeftButton:
            self.left_button = False
        else:
            return super(ZoomView, self).mouseReleaseEvent(event)

    def mouseMoveEvent(self, event):

        if event.buttons() == QtCore.Qt.NoButton:
            return super(ZoomView, self).mouseMoveEvent(event)

        new_pos = event.pos()
        diff_x = self.mouse_pos.x() - new_pos.x()
        diff_y = self.mouse_pos.y() - new_pos.y()
        if self.alt_key and self.mid_button and not self.left_button:
            # pan the screen

            h_scroll = self.horizontalScrollBar()
            v_scroll = self.verticalScrollBar()

            H_scrollFinal = h_scroll.value() + diff_x
            V_scrollFinal = v_scroll.value() + diff_y
            h_scroll.setValue(H_scrollFinal)
            v_scroll.setValue(V_scrollFinal)

            self.mouse_pos = new_pos

        elif self.alt_key and self.left_button and self.mid_button:
            # zoom
            actualScale = self.transform().m11()
            coefDdiff_x = diff_x * 0.004
            scaleFactor = actualScale - coefDdiff_x
            if scaleFactor > 0.05 and scaleFactor < 3:
                matrice = QtGui.QTransform(scaleFactor, 0, 0, 0, scaleFactor, 0, 0, 0, 1)
                self.setTransform(matrice, combine=False)
                h_scroll = self.horizontalScrollBar()
                v_scroll = self.verticalScrollBar()

                self.mouse_pos = new_pos

        else:
            return super(ZoomView, self).mouseMoveEvent(event)

【问题讨论】:

    标签: python qgraphicsview pyside2 qgraphicsitem


    【解决方案1】:

    好的,找到了解决方案。

    当你继承 QGraphicsView 并覆盖这些鼠标方法时

    mousePressEvent()
    mouseMoveEvent()
    mouseReleaseEvent()
    

    在运行自定义缩放/平移代码之前,您需要在每个方法的开头放置一个“if”语句,以检查鼠标是否在您的某个项目上。如果鼠标悬停在像矩形或椭圆这样的项目上,那么只需运行该方法的超级并返回。此外,如果选择了矩形或椭圆,则运行 super 并返回。

    这是一个例子:

    class MyView(QGraphicsView):
    
        def mousePressEvent(self, event):
    
            # check if clicking on a button first or if a button is selected
            scene = self.scene()
            items = scene.items(event.localPos())
    
            if self.selected_items():
                super(Picker_View, self).mousePressEvent(event)
                return
    
            if items and isinstance(items[0], Ellipse_Button):
                # QGraphicsScene.mousePressEvent(self, event)
                super(Picker_View, self).mousePressEvent(event)
                return
    
            self.foo()
    
        def selected_items(self):
            '''
            Checks if any items in the graphics scene are selected
            Returns:
                (boolean)
    
            '''
            scene = self.scene()
            elements = scene.items()
            for element in elements:
                if element.isSelected():
                    return True
                else:
                    pass
            return False
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-25
      • 1970-01-01
      • 2021-12-09
      • 2011-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-29
      相关资源
      最近更新 更多