仅针对 QGraphicsView 禁用 wheelEvent,而不针对内部小部件

Disable wheelEvent for QGraphicsView only, and not for the inside widgets

我有一个 QGraphicsView 的小部件 QGraphicsProxyWidgetQScrollArea。我正在尝试禁用 QGraphicsViewwheelEvent 而不影响 ProxyWidgetwheelEvent:

class JobBuilderView(QGraphicsView):
    def __init__(self, scene, parent=None):
        super().__init__(parent) 
        .
        .
        .
        self.viewport().installEventFilter(self)

    def eventFilter(self, qobject, event):
        if (event.type() == QEvent.Wheel and
            qobject is self.viewport()):
            modifiers = QApplication.keyboardModifiers()
            if modifiers == Qt.ControlModifier:
                zoomOutFactor = 1 / self.zoomInFactor
                if event.angleDelta().y() > 0:
                    zoomFactor = self.zoomInFactor
                    self.zoom += self.zoomStep
                else:
                    zoomFactor = zoomOutFactor
                    self.zoom -= self.zoomStep

                clamped = False
                if self.zoom < self.zoomRange[0]: self.zoom, clamped = 
                self.zoomRange[0], True
                if self.zoom > self.zoomRange[1]: self.zoom, clamped = 
                self.zoomRange[1], True
                if not clamped or self.zoomClamp is False:
                    self.scale(zoomFactor, zoomFactor)
                return True
            else:
                event.ignore()
                return True
        return super().eventFilter(qobject, event)

但是,此方法禁用所有 ProxyWidgetswheelEvent

这个问题有什么解决办法吗?

我已经按照@musicamante 的建议更改了调用,但是我正在实现的缩放功能无法正常工作,因为它应该使用 event.type() == QEvent.Wheelevent.angleDelta().y() > 0:

def eventFilter(self, qobject, event):
    zoomInFactor = 1.25
    zoomClamp    = True     
    zoom         = 10
    zoomStep     = 1
    zoomRange    = [0, 10]
    if event.type() == event.GraphicsSceneWheel:
        if QApplication.keyboardModifiers() and Qt.ControlModifier:
            qobject.wheelEvent(event)
            zoomOutFactor = 1 / self.zoomInFactor
            if event.delta() == 120:
                zoomFactor = self.zoomInFactor
                self.zoom += self.zoomStep
            elif event.delta() == -120:
                zoomFactor = zoomOutFactor
                self.zoom -= self.zoomStep

            clamped = False
            if self.zoom < self.zoomRange[0]: self.zoom, clamped = self.zoomRange[0], True
            if self.zoom > self.zoomRange[1]: self.zoom, clamped = self.zoomRange[1], True
            if not clamped or self.zoomClamp is False:
                self.scale(zoomFactor, zoomFactor)
            
            return True
        else:
            qobject.wheelEvent(event)
            event.setAccepted(True)
        
            return True 
    return super().eventFilter(qobject, event)

有什么建议吗,我该如何解决这个缩放功能?

当视图接收到输入事件时,它会根据它创建一个图形场景事件,并将其发送到场景。对于车轮事件,它是 QGraphicsSceneWheelEvent.

如果场景确实接受了事件(这通常意味着一个项目已经处理了它[1]),事件是不会 传播到父级,就像标准小部件的任何其他事件一样。

对于图形视图,如果场景不接受事件,它会自动将原始轮子事件发送到滚动条(QAbstractScrollArea 的默认实现)。

如果必须忽略事件,解决方案是始终在调用基本实现之后将事件设置为已接受。

对于子类:

class Scene(QGraphicsScene):
    def wheelEvent(self, event):
        super().wheelEvent(event)
        event.setAccepted(True)

或者,在场景中安装一个事件过滤器:

class JobBuilderView(QGraphicsView):
    def __init__(self, scene, parent=None):
        super().__init__(parent) 
        # ...
        self.scene().installEventFilter(self)

    def eventFilter(self, obj, event):
        if event.type() == event.GraphicsSceneWheel:
            obj.wheelEvent(event)
            event.setAccepted(True)
            return True
        return super().eventFilter(obj, event)

[1] 处理事件及其接受状态并不总是一致:事件可以被处理 忽略(通常将其传播到父级),或者它可以 处理并仍然被接受。前者是 widget 的鼠标移动事件的情况,它只能改变 widget 的外观,而父级由于其他原因仍然需要处理它,而后者发生在不应将事件传播给父级时(鼠标按下在禁用的小部件上)。