pythonmatplotlibpyqt5pyside2matplotlib-widget

How to reset/ start a new polygon with embeded matplotlib in pyqt


I am trying to create a polygon selector in my PySide2 application. Selector is working fine, but then I want to add functionality to reset/start new polygon when escape button is pressed. Something similar to this PolygonSelector example, when escape is pressed.

https://matplotlib.org/stable/gallery/widgets/polygon_selector_demo.html

I tried method .clear() but it does not seems to work for me.

import sys

import numpy as np
from PySide2 import QtWidgets, QtGui

from matplotlib.backends.backend_qtagg import (
    FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
from matplotlib.widgets import PolygonSelector

class ApplicationWindow(QtWidgets.QMainWindow):
    def __init__(self):

        super().__init__()
        self._main = QtWidgets.QWidget()
        self.setCentralWidget(self._main)

        shortcut_clear_selection = QtWidgets.QShortcut(QtGui.QKeySequence("Escape"), self._main)
        shortcut_clear_selection.activated.connect(self.callback_clear_selection)

        layout = QtWidgets.QVBoxLayout(self._main)

        static_canvas = FigureCanvas(Figure(figsize=(5, 3)))
        layout.addWidget(NavigationToolbar(static_canvas, self))
        layout.addWidget(static_canvas)

        ax = static_canvas.figure.subplots()
        t = np.linspace(0, 10, 501)
        ax.plot(t, np.tan(t), ".")
        self.poly = PolygonSelector(ax, self.onselect)

    def onselect(self, verts):
        pass

    def callback_clear_selection(self):
        # HERE should be the reset part
        self.poly.clear()

if __name__ == "__main__":
    qapp = QtWidgets.QApplication(sys.argv)

    app = ApplicationWindow()
    app.show()
    app.activateWindow()
    app.raise_()
    qapp.exec_()

Solution

  • Problem is, that ESC key release event is not handled by PolygonSelector but Your callback. Therefore, to clear polygon and restart creation of polygon You have to clear polygon data and show selector again. clear method was just hiding selector, but polygon data stayed unchanged.

    Change Your callback code into this:

    def callback_clear_selection(self):
        # HERE should be the reset
        self.poly._xs, self.poly._ys = [0], [0]
        self.poly._selection_completed = False
        self.poly.set_visible(True)
    

    Now, when You press ESC, polygon should be removed and You can start selection of new one.