diff --git a/skimage/viewer/canvastools/base.py b/skimage/viewer/canvastools/base.py index 05709c61..6fcda9c4 100644 --- a/skimage/viewer/canvastools/base.py +++ b/skimage/viewer/canvastools/base.py @@ -84,6 +84,16 @@ class CanvasToolBase(object): for artist in self._artists: self.ax.draw_artist(artist) + def remove(self): + """Remove artists and events from axes. + + Note that the naming here mimics the interface of Matplotlib artists. + """ + #TODO: For some reason, RectangleTool doesn't get properly removed + self.disconnect_events() + for a in self._artists: + a.remove() + def redraw(self): """Redraw image and canvas artists. diff --git a/skimage/viewer/plugins/base.py b/skimage/viewer/plugins/base.py index 9f5d25dc..f7f9882c 100644 --- a/skimage/viewer/plugins/base.py +++ b/skimage/viewer/plugins/base.py @@ -44,8 +44,9 @@ class Plugin(QDialog): name : str Name of plugin. This is displayed as the window title. artist : list - List of Matplotlib artists. Any artists created by the plugin should - be added to this list so that it gets cleaned up on close. + List of Matplotlib artists and canvastools. Any artists created by the + plugin should be added to this list so that it gets cleaned up on + close. Examples -------- @@ -190,8 +191,7 @@ class Plugin(QDialog): def closeEvent(self, event): """On close disconnect all artists and events from ImageViewer. - Note that events must be connected using `self.connect_image_event` and - artists must be appended to `self.artists`. + Note that artists must be appended to `self.artists`. """ self.disconnect_image_events() self.remove_image_artists() @@ -222,6 +222,6 @@ class Plugin(QDialog): self.image_viewer.disconnect_event(c) def remove_image_artists(self): - """Disconnect artists that are connected to the image viewer.""" + """Remove artists that are connected to the image viewer.""" for a in self.artists: - self.image_viewer.remove_artist(a) + a.remove() diff --git a/skimage/viewer/plugins/crop.py b/skimage/viewer/plugins/crop.py index 97a43cb5..39e59eb8 100644 --- a/skimage/viewer/plugins/crop.py +++ b/skimage/viewer/plugins/crop.py @@ -21,6 +21,7 @@ class Crop(Plugin): self.rect_tool = RectangleTool(self.image_viewer.ax, maxdist=self.maxdist, on_enter=self.crop) + self.artists.append(self.rect_tool) def help(self): helpstr = ("Crop tool", diff --git a/skimage/viewer/plugins/measure.py b/skimage/viewer/plugins/measure.py index e05f8fe8..4911a1ff 100644 --- a/skimage/viewer/plugins/measure.py +++ b/skimage/viewer/plugins/measure.py @@ -35,6 +35,7 @@ class Measure(Plugin): self.line_tool = LineTool(self.image_viewer.ax, maxdist=self.maxdist, on_move=self.line_changed) + self.artists.append(self.line_tool) def help(self): helpstr = ("Measure tool", diff --git a/skimage/viewer/viewers/core.py b/skimage/viewer/viewers/core.py index 83ef65a3..ef450b3e 100644 --- a/skimage/viewer/viewers/core.py +++ b/skimage/viewer/viewers/core.py @@ -83,14 +83,6 @@ class ImageViewer(QMainWindow): self.image = image.copy() self.plugins = [] - # List of axes artists to check for removal. - self._axes_artists = [self.ax.artists, - self.ax.collections, - self.ax.images, - self.ax.lines, - self.ax.patches, - self.ax.texts] - self.layout = QtGui.QVBoxLayout(self.main_widget) self.layout.addWidget(self.canvas) @@ -196,25 +188,6 @@ class ImageViewer(QMainWindow): """Disconnect callback by its id (returned by `connect_event`).""" self.canvas.mpl_disconnect(callback_id) - def remove_artist(self, artist): - """Disconnect matplotlib artist from image viewer. - - The `closeEvent` method of a Plugin should remove artists (Matplotlib - lines, markers, etc.) from the viewer so that they aren't stranded. - - Parameters - ---------- - artist : Matplotlib Artist - Artists created by Matplotlib functions (e.g., `plot` returns list - of `Line2D` artists) should be saved by the plugin for removal. - """ - # Note: an `add_artist` method is unnecessary since Matplotlib - - # There's probably a smarter way to find where the artist is stored. - for artist_list in self._axes_artists: - if artist in artist_list: - artist_list.remove(artist) - def _update_status_bar(self, event): if event.inaxes and event.inaxes.get_navigate(): self.status_message(self._format_coord(event.xdata, event.ydata))