仅针对 QGraphicsView 禁用 wheelEvent,而不针对内部小部件
Disable wheelEvent for QGraphicsView only, and not for the inside widgets
我有一个 QGraphicsView
的小部件 QGraphicsProxyWidget
和 QScrollArea
。我正在尝试禁用 QGraphicsView
的 wheelEvent
而不影响 ProxyWidget
的 wheelEvent
:
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)
但是,此方法禁用所有 ProxyWidgets
的 wheelEvent
。
这个问题有什么解决办法吗?
我已经按照@musicamante 的建议更改了调用,但是我正在实现的缩放功能无法正常工作,因为它应该使用 event.type() == QEvent.Wheel
和 event.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 的外观,而父级由于其他原因仍然需要处理它,而后者发生在不应将事件传播给父级时(鼠标按下在禁用的小部件上)。
我有一个 QGraphicsView
的小部件 QGraphicsProxyWidget
和 QScrollArea
。我正在尝试禁用 QGraphicsView
的 wheelEvent
而不影响 ProxyWidget
的 wheelEvent
:
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)
但是,此方法禁用所有 ProxyWidgets
的 wheelEvent
。
这个问题有什么解决办法吗?
我已经按照@musicamante 的建议更改了调用,但是我正在实现的缩放功能无法正常工作,因为它应该使用 event.type() == QEvent.Wheel
和 event.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 的外观,而父级由于其他原因仍然需要处理它,而后者发生在不应将事件传播给父级时(鼠标按下在禁用的小部件上)。