I'm trying to optimize example (https://matplotlib.org/stable/gallery/widgets/check_buttons.html) for my task in a small project.I have an example that works:
from PyQt5.QtWidgets import QApplicationimport numpy as npfrom matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvasfrom matplotlib.figure import Figurefrom matplotlib.widgets import CheckButtonsfrom ShortCircuitCalc.gui.windows import CustomGraphicView, MainWindowfrom PyQt5 import QtWidgetsclass Window(CustomGraphicView): def __init__(self, parent=None): super(Window, self).__init__(parent) self.canvas = FigureCanvas(Figure(figsize=(5, 3))) t = np.arange(0.0, 2.0, 0.01) s0 = np.sin(2 * np.pi * t) s1 = np.sin(4 * np.pi * t) s2 = np.sin(6 * np.pi * t) ax = self.canvas.figure.subplots() l0, = ax.plot(t, s0, visible=False, lw=2, color="k", label="2 Hz") l1, = ax.plot(t, s1, lw=2, color="r", label="4 Hz") l2, = ax.plot(t, s2, lw=2, color="g", label="6 Hz") self.canvas.figure.subplots_adjust(left=0.2) self.lines = [l0, l1, l2] rax = self.canvas.figure.add_axes([0.05, 0.4, 0.1, 0.15]) self.labels = [str(line.get_label()) for line in self.lines] visibility = [line.get_visible() for line in self.lines] self.check = CheckButtons(rax, self.labels, visibility) self.check.on_clicked(self.is_click) def is_click(self, label): index = self.labels.index(label) self.lines[index].set_visible(not self.lines[index].get_visible()) self.canvas.draw()def main(): import sys app = QApplication(sys.argv) w = MainWindow() r = Window() w.resultView.scene = QtWidgets.QGraphicsScene() w.resultView.scene.addWidget(r.canvas) w.resultView.setScene(w.resultView.scene) w.show() sys.exit(app.exec_())if __name__ == "__main__": main()
I get correctly next working model:
But I want to get such an active model for each subplot in my figure.I tried to rework the above example and even got the layout I needed, but the buttons on it are not interactive. How can I refine this to get each interactive subplot. At the moment I have this code and these results:
from PyQt5.QtWidgets import QApplicationimport numpy as npfrom matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvasfrom matplotlib.figure import Figurefrom matplotlib.widgets import CheckButtonsfrom ShortCircuitCalc.gui.windows import CustomGraphicView, MainWindowfrom PyQt5 import QtWidgetsclass Window(CustomGraphicView): def __init__(self, parent=None): super(Window, self).__init__(parent) ncols = 5 nrows = 8 self.canvas = FigureCanvas(Figure(figsize=(ncols * 5, nrows * 3))) t = np.arange(0.0, 2.0, 0.01) s0 = np.sin(2 * np.pi * t) s1 = np.sin(4 * np.pi * t) s2 = np.sin(6 * np.pi * t) ax = self.canvas.figure.subplots(ncols=ncols, nrows=nrows) for col in range(ncols): for row in range(nrows): (l0,) = ax[row, col].plot(t, s0, visible=False, lw=2, color="k", label="2 Hz") (l1,) = ax[row, col].plot(t, s1, lw=2, color="r", label="4 Hz") (l2,) = ax[row, col].plot(t, s2, lw=2, color="g", label="6 Hz") lines = [l0, l1, l2] rax = ax[row, col].inset_axes([0.05, 0.4, 0.1, 0.15]) labels = [str(line.get_label()) for line in lines] visibility = [line.get_visible() for line in lines] self.check = CheckButtons(rax, labels, visibility) self.check.on_clicked(self.is_click) self.canvas.figure.subplots_adjust(left=0.2) def is_click(self, label): # index = self.labels.index(label) # self.lines[index].set_visible(not self.lines[index].get_visible()) # self.canvas.draw() print('Button is pressed')def main(): import sys app = QApplication(sys.argv) w = MainWindow() r = Window() w.resultView.scene = QtWidgets.QGraphicsScene() w.resultView.scene.addWidget(r.canvas) w.resultView.setScene(w.resultView.scene) w.show() sys.exit(app.exec_())if __name__ == "__main__": main()
In my code, CustomGraphicView is just a QGraphicsView with some navigation tweaks. At the moment the implementation of CustomGraphicView and its use cases are as follows:
import sysimport numpy as npimport matplotlibimport matplotlib.pyplot as pltfrom matplotlib.backends.backend_qt5agg import ( FigureCanvasQTAgg as FigCanvas, NavigationToolbar2QT as NavToolbar,)from PyQt5 import QtWidgets, QtCore, QtGuiclass CustomGraphicView(QtWidgets.QGraphicsView): def __init__(self, parent: QtWidgets = None, figure: matplotlib.figure.Figure = None, title: str = 'Viewer') -> None: super(CustomGraphicView, self).__init__(parent) self._title = title self._figure = figure self._scene = QtWidgets.QGraphicsScene() if parent is not None: self._canvas = None else: self._canvas = FigCanvas(self._figure) self._scene.addWidget(self._canvas) self.setScene(self._scene) self.setWindowTitle(self._title) self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse) # Start viewing position self.horizontalScrollBar().setSliderPosition(1) self.verticalScrollBar().setSliderPosition(1) self._zoom = 0 self._mousePressed = False self._drag_pos = None self.save_model_action = QtWidgets.QAction('Save model as ...', self) self.save_model_action.triggered.connect(self.save_model) self.save_fragment_action = QtWidgets.QAction('Save fragment as ...', self) self.save_fragment_action.triggered.connect(self.save_fragment) def set_figure(self, figure): self._figure = figure self._canvas = FigCanvas(self._figure) self._scene.addWidget(self._canvas) self.setScene(self._scene) def mousePressEvent(self, event: QtCore.Qt.MouseButton.LeftButton) -> None: if event.button() == QtCore.Qt.MouseButton.LeftButton: self._mousePressed = True self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.OpenHandCursor)) self._drag_pos = event.pos() event.accept() else: super(CustomGraphicView, self).mousePressEvent(event) def mouseMoveEvent(self, event: QtCore.Qt.MouseButton.LeftButton) -> None: if self._mousePressed: new_pos = event.pos() diff = new_pos - self._drag_pos self._drag_pos = new_pos self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - diff.x()) self.verticalScrollBar().setValue(self.verticalScrollBar().value() - diff.y()) self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.OpenHandCursor)) else: super(CustomGraphicView, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event: QtCore.Qt.MouseButton.LeftButton) -> None: if event.button() == QtCore.Qt.MouseButton.LeftButton: self._mousePressed = False self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.ArrowCursor)) super(CustomGraphicView, self).mouseReleaseEvent(event) def wheelEvent(self, event: QtCore.Qt.KeyboardModifier.ControlModifier) -> None: modifiers = QtWidgets.QApplication.keyboardModifiers() if modifiers == QtCore.Qt.KeyboardModifier.ControlModifier: if event.angleDelta().y() > 0: factor = 1.25 self._zoom += 1 else: factor = 0.8 self._zoom -= 1 if self._zoom > -1: self.scale(factor, factor) else: self._zoom = 0 else: super(CustomGraphicView, self).wheelEvent(event) def contextMenuEvent(self, event: QtGui.QContextMenuEvent) -> None: # Creating context menu menu = QtWidgets.QMenu(self) menu.addAction(self.save_model_action) # Creating / adding separator separator = QtWidgets.QAction(self) separator.setSeparator(True) menu.addAction(separator) menu.addAction(self.save_fragment_action) menu.exec(event.globalPos()) def save_model(self): NavToolbar.save_figure(self._figure) def save_fragment(self): rect_region = QtCore.QRect(0, 0, self.width() - self.verticalScrollBar().width(), self.height() - self.horizontalScrollBar().height()) pixmap = self.grab(rect_region) fname = QtWidgets.QFileDialog.getSaveFileName(self, 'Save fragment as ...', 'image.png','Portable Network Graphics (*.png);;''Joint Photographic Experts Group (*.jpeg *.jpg)')[0] if fname: pixmap.save(fname)if __name__ == '__main__': # Some figure fig, ax = plt.subplots() t = np.arange(0.0, 2.0, 0.01) s0 = np.sin(2 * np.pi * t) s1 = np.sin(4 * np.pi * t) s2 = np.sin(6 * np.pi * t) ax.plot(t, s0, lw=2, color="k", label="2 Hz") ax.plot(t, s1, lw=2, color="r", label="4 Hz") ax.plot(t, s2, lw=2, color="g", label="6 Hz") app = QtWidgets.QApplication(sys.argv) window = CustomGraphicView(parent=None, figure=fig) window.show() sys.exit(app.exec_()) # Or i may # app = QtWidgets.QApplication(sys.argv) # window = CustomGraphicView(parent=None, figure=None) # window.set_figure(fig) # window.show() # sys.exit(app.exec_())