diff --git a/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py b/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py index eee677abe9c1793f6447644f0db933df9da9a30a..e35ba7558cdf9ef8ca4316a967318c5773f54b81 100644 --- a/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py +++ b/sohstationviewer/view/plotting/plotting_widget/plotting_axes.py @@ -58,6 +58,9 @@ class PlottingAxes: canvas: the canvas inside main_widget associates with fig """ self.canvas = Canvas(self.fig) + # Setting a custom property so we can distinguish the plot canvas from + # other widgets. + self.canvas.setProperty('is_plot_canvas', True) self.canvas.setParent(self.parent.main_widget) # canvas background is transparent diff --git a/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py b/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py index 056fd062d1d6071cb0515cab38a59216c7ded295..b2911012e8b6ba57426aea9c32300a96b5f65de6 100644 --- a/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py +++ b/sohstationviewer/view/plotting/plotting_widget/plotting_widget.py @@ -7,7 +7,7 @@ import numpy as np import matplotlib.text from matplotlib import pyplot as pl -from PySide6.QtCore import QTimer, Qt +from PySide6.QtCore import Qt, QTimer, QEvent, QObject from PySide6 import QtCore, QtWidgets from PySide6.QtWidgets import QWidget, QApplication, QTextBrowser @@ -184,6 +184,8 @@ class PlottingWidget(QtWidgets.QScrollArea): plotting_axes: object that helps creating axes for plotting """ self.plotting_axes = PlottingAxes(self, main_window) + self.plotting_axes.canvas.setParent(self.main_widget) + self.plotting_axes.canvas.installEventFilter(self) self.setWidget(self.main_widget) @@ -327,6 +329,33 @@ class PlottingWidget(QtWidgets.QScrollArea): self.zoom_marker2.set_visible(False) self.plotting_axes.canvas.draw() + def eventFilter(self, target: QObject, event: QEvent) -> bool: + """ + Reimplements: QObject.eventFilter() + + Filter mouse wheel events that are sent to the matplotlib plot canvas + and handle them. Pass on all other events. + + Matplotlib plot canvas swallows events. This is fine for some events, + but mouse wheel events has to be processed by the scroll area for + scrolling to happen. This method ensures that scroll events get to + the scroll area before the plot canvas. + + :param target: the object the event is being sent to + :param event: the event being sent + :return: True if the event is filtered out, False otherwise + """ + is_scroll_on_plot = (target.property('is_plot_canvas') is not None and + event.type() == QEvent.Type.Wheel) + if is_scroll_on_plot: + # QScrollArea can process QWheelEvent with its wheelEvent() method, + # but it ignores any QWheelEvent it is sent. We call wheelEvent() + # explicitly to work around this issue. + self.wheelEvent(event) + return False + else: + return super().eventFilter(target, event) + def on_pick_event(self, event): """ When click mouse on a clickable data point (dot with picker=True in