From 0904ec597bf39544532a553ce2c2ad9ad75b033f Mon Sep 17 00:00:00 2001 From: ruyer Date: Wed, 17 Jun 2026 17:21:58 +0200 Subject: [PATCH 1/2] [PlotWidget] Allow directive zoom with shortcut ALT and SHIFT like h5web --- src/silx/gui/plot/PlotInteraction.py | 20 +++++++++++++++----- src/silx/gui/plot/backends/BackendOpenGL.py | 2 +- src/silx/gui/plot/tools/menus.py | 6 +++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/silx/gui/plot/PlotInteraction.py b/src/silx/gui/plot/PlotInteraction.py index 3dfe739a34..6901303f19 100644 --- a/src/silx/gui/plot/PlotInteraction.py +++ b/src/silx/gui/plot/PlotInteraction.py @@ -1896,18 +1896,28 @@ def _onWheel(self, x: float, y: float, angle: float): if not self.isZoomOnWheelEnabled(): return + if angle == 0: + return plotWidget = self.parent() if plotWidget is None: return # All axes are enabled if keep aspect ratio is on - enabledAxes = ( - EnabledAxes() - if plotWidget.isKeepDataAspectRatio() - else self.getZoomEnabledAxes() - ) + if plotWidget.isKeepDataAspectRatio(): + enabledAxes = EnabledAxes() + else: + modifiers = qt.QApplication.keyboardModifiers() + shiftPressed = modifiers & qt.Qt.ShiftModifier + altPressed = modifiers & qt.Qt.AltModifier + if shiftPressed or altPressed: + enabledAxes = EnabledAxes( + xaxis=altPressed, yaxis=shiftPressed, y2axis=shiftPressed + ) + else: + enabledAxes = self.getZoomEnabledAxes() if enabledAxes.isDisabled(): return scale = 1.1 if angle > 0 else 1.0 / 1.1 + applyZoomToPlot(plotWidget, scale, (x, y), enabledAxes) diff --git a/src/silx/gui/plot/backends/BackendOpenGL.py b/src/silx/gui/plot/backends/BackendOpenGL.py index 17cff0bdcd..74bd16d386 100755 --- a/src/silx/gui/plot/backends/BackendOpenGL.py +++ b/src/silx/gui/plot/backends/BackendOpenGL.py @@ -321,7 +321,7 @@ def mouseReleaseEvent(self, event): event.accept() def wheelEvent(self, event): - delta = event.angleDelta().y() + delta = event.angleDelta().x() + event.angleDelta().y() angleInDegrees = delta / 8.0 x, y = qt.getMouseEventPosition(event) self._plot.onMouseWheel(x, y, angleInDegrees) diff --git a/src/silx/gui/plot/tools/menus.py b/src/silx/gui/plot/tools/menus.py index ca8a1ba31f..6373f7040d 100644 --- a/src/silx/gui/plot/tools/menus.py +++ b/src/silx/gui/plot/tools/menus.py @@ -52,9 +52,9 @@ def __init__(self, plot: PlotWidget, parent: qt.QWidget | None = None): self.__plotRef = weakref.ref(plot) self.addSection("Enabled axes") - self.__xAxisAction = qt.QAction("X axis", parent=self) - self.__yAxisAction = qt.QAction("Y left axis", parent=self) - self.__y2AxisAction = qt.QAction("Y right axis", parent=self) + self.__xAxisAction = qt.QAction("X axis (alt)", parent=self) + self.__yAxisAction = qt.QAction("Y left axis (shift)", parent=self) + self.__y2AxisAction = qt.QAction("Y right axis (shift)", parent=self) for action in (self.__xAxisAction, self.__yAxisAction, self.__y2AxisAction): action.setCheckable(True) From 7d3b2c6debaf2d21b483fb52f5d66b58909eca0e Mon Sep 17 00:00:00 2001 From: ruyer Date: Fri, 26 Jun 2026 16:26:22 +0200 Subject: [PATCH 2/2] [PlotWidget] Allow directive zoom with shortcut ALT and SHIFT like h5web --- .../gui/plot/backends/BackendMatplotlib.py | 24 +++++++++++++++++++ src/silx/gui/plot/backends/BackendOpenGL.py | 9 ++++++- src/silx/gui/plot/tools/menus.py | 6 ++--- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/silx/gui/plot/backends/BackendMatplotlib.py b/src/silx/gui/plot/backends/BackendMatplotlib.py index 823c4722df..6e17a0eceb 100755 --- a/src/silx/gui/plot/backends/BackendMatplotlib.py +++ b/src/silx/gui/plot/backends/BackendMatplotlib.py @@ -1695,3 +1695,27 @@ def setGraphCursorShape(self, cursor): else: cursor = self._QT_CURSORS[cursor] FigureCanvasQTAgg.setCursor(self, qt.QCursor(cursor)) + + def wheelEvent(self, event): + # https://github.com/qt/qtbase/blob/120883a028a59864dc7691dd1efa318bd602755d/src/plugins/platforms/xcb/qxcbwindow.cpp#L1955-L1956 + # qt xcb plugin put angleDelta in x rather than in y when alt modifier is pressed. + # matplotlib/matplotlib#25671 marked as 'won't fix' + # Fix here as we want to be able to use alt modifier in silx plot. + # https://github.com/silx-kit/silx/pull/4631 + if event.angleDelta().y() == 0: + event = qt.QWheelEvent( + event.position(), + event.globalPosition(), + event.pixelDelta(), + qt.QPoint(0, event.angleDelta().x()), + event.buttons(), + event.modifiers(), + event.phase(), + event.isInverted(), + event.source(), + event.pointingDevice(), + ) + super().wheelEvent(event) + return + + super().wheelEvent(event) diff --git a/src/silx/gui/plot/backends/BackendOpenGL.py b/src/silx/gui/plot/backends/BackendOpenGL.py index 74bd16d386..6c4827362a 100755 --- a/src/silx/gui/plot/backends/BackendOpenGL.py +++ b/src/silx/gui/plot/backends/BackendOpenGL.py @@ -321,7 +321,14 @@ def mouseReleaseEvent(self, event): event.accept() def wheelEvent(self, event): - delta = event.angleDelta().x() + event.angleDelta().y() + delta = event.angleDelta().y() + # https://github.com/qt/qtbase/blob/120883a028a59864dc7691dd1efa318bd602755d/src/plugins/platforms/xcb/qxcbwindow.cpp#L1955-L1956 + # qt xcb plugin put angleDelta in x rather than in y when alt modifier is pressed. + # matplotlib/matplotlib#25671 marked as 'won't fix' + # Fix here as we want to be able to use alt modifier in silx plot. + # https://github.com/silx-kit/silx/pull/4631 + if event.angleDelta().y() == 0: + delta = event.angleDelta().x() angleInDegrees = delta / 8.0 x, y = qt.getMouseEventPosition(event) self._plot.onMouseWheel(x, y, angleInDegrees) diff --git a/src/silx/gui/plot/tools/menus.py b/src/silx/gui/plot/tools/menus.py index 6373f7040d..53ca4bf020 100644 --- a/src/silx/gui/plot/tools/menus.py +++ b/src/silx/gui/plot/tools/menus.py @@ -52,9 +52,9 @@ def __init__(self, plot: PlotWidget, parent: qt.QWidget | None = None): self.__plotRef = weakref.ref(plot) self.addSection("Enabled axes") - self.__xAxisAction = qt.QAction("X axis (alt)", parent=self) - self.__yAxisAction = qt.QAction("Y left axis (shift)", parent=self) - self.__y2AxisAction = qt.QAction("Y right axis (shift)", parent=self) + self.__xAxisAction = qt.QAction("X axis (Alt+Wheel)", parent=self) + self.__yAxisAction = qt.QAction("Y left axis (Shift+Wheel)", parent=self) + self.__y2AxisAction = qt.QAction("Y right axis (Shift+Wheel)", parent=self) for action in (self.__xAxisAction, self.__yAxisAction, self.__y2AxisAction): action.setCheckable(True)