mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-29 05:17:50 +08:00
36b0fbd84e
This clarifies action since these events are on the image viewer, not the plugin.
145 lines
4.8 KiB
Python
145 lines
4.8 KiB
Python
from PyQt4 import QtGui
|
|
from PyQt4.QtCore import Qt
|
|
|
|
import matplotlib as mpl
|
|
|
|
|
|
class Plugin(QtGui.QDialog):
|
|
"""Base class for widgets that interact with the axes.
|
|
|
|
Parameters
|
|
----------
|
|
image_viewer : ImageViewer instance.
|
|
Window containing image used in measurement/manipulation.
|
|
callback : function
|
|
Function that gets called to update ImageViewer. Alternatively, this
|
|
can also be defined as a method in a Plugin subclass.
|
|
height, width : int
|
|
Size of plugin window in pixels.
|
|
useblit : bool
|
|
If True, use blitting to speed up animation. Only available on some
|
|
backends. If None, set to True when using Agg backend, otherwise False.
|
|
|
|
Attributes
|
|
----------
|
|
image_viewer : ImageViewer
|
|
Window containing image used in measurement.
|
|
"""
|
|
name = 'Plugin'
|
|
draws_on_image = False
|
|
|
|
def __init__(self, image_filter=None, height=0, width=400, useblit=None):
|
|
super(Plugin, self).__init__()
|
|
|
|
self.image_viewer = None
|
|
if image_filter is not None:
|
|
self.image_filter = image_filter
|
|
|
|
self.setWindowTitle(self.name)
|
|
self.layout = QtGui.QGridLayout(self)
|
|
self.resize(width, height)
|
|
self.row = 0
|
|
|
|
self.arguments = []
|
|
self.keyword_arguments= {}
|
|
|
|
if useblit is None:
|
|
useblit = True if mpl.backends.backend.endswith('Agg') else False
|
|
self.useblit = useblit
|
|
self.cids = []
|
|
self.artists = []
|
|
|
|
@property
|
|
def image_viewer(self):
|
|
if self._image_viewer is None:
|
|
raise RuntimeError("Plugin is not attached to ImageViewer")
|
|
return self._image_viewer
|
|
|
|
@image_viewer.setter
|
|
def image_viewer(self, image_viewer):
|
|
self._image_viewer = image_viewer
|
|
|
|
def attach(self, image_viewer):
|
|
self.setParent(image_viewer)
|
|
self.setWindowFlags(Qt.Dialog)
|
|
|
|
self.image_viewer = image_viewer
|
|
self.image_viewer.plugins.append(self)
|
|
#TODO: Always passing image as first argument may be bad assumption.
|
|
self.arguments.append(self.image_viewer.original_image)
|
|
|
|
if self.draws_on_image:
|
|
self.connect_image_event('draw_event', self.on_draw)
|
|
|
|
def on_draw(self, event):
|
|
"""Save image background when blitting.
|
|
|
|
The saved image is used to "clear" the figure before redrawing artists.
|
|
"""
|
|
if self.useblit:
|
|
bbox = self.image_viewer.ax.bbox
|
|
self.img_background = self.image_viewer.canvas.copy_from_bbox(bbox)
|
|
|
|
def filter_image(self, *args):
|
|
arguments = [self._get_value(a) for a in self.arguments]
|
|
kwargs = dict([(name, self._get_value(a))
|
|
for name, a in self.keyword_arguments.iteritems()])
|
|
self.image_filter(*arguments, **kwargs)
|
|
|
|
def _get_value(self, param):
|
|
return param if not hasattr(param, 'val') else param.val()
|
|
|
|
def add_widget(self, widget):
|
|
if widget.ptype == 'kwarg':
|
|
name = widget.name.replace(' ', '_')
|
|
self.keyword_arguments[name] = widget
|
|
widget.callback = self.filter_image
|
|
elif widget.ptype == 'arg':
|
|
self.arguments.append(widget)
|
|
widget.callback = self.filter_image
|
|
elif widget.ptype == 'plugin':
|
|
widget.callback = self.update_plugin
|
|
self.layout.addWidget(widget, self.row, 0)
|
|
self.row += 1
|
|
|
|
def update_plugin(self, name, value):
|
|
setattr(self, name, value)
|
|
|
|
def closeEvent(self, event):
|
|
"""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`.
|
|
"""
|
|
self.disconnect_image_events()
|
|
self.remove_image_artists()
|
|
self.image_viewer.plugins.remove(self)
|
|
self.image_viewer.redraw()
|
|
self.close()
|
|
|
|
def connect_image_event(self, event, callback):
|
|
"""Connect callback with an event in the image viewer.
|
|
|
|
This should be used in lieu of `figure.canvas.mpl_connect` since this
|
|
function stores call back ids for later clean up.
|
|
|
|
Parameters
|
|
----------
|
|
event : str
|
|
Matplotlib event.
|
|
callback : function
|
|
Callback function with a matplotlib Event object as its argument.
|
|
"""
|
|
cid = self.image_viewer.connect_event(event, callback)
|
|
self.cids.append(cid)
|
|
|
|
def disconnect_image_events(self):
|
|
"""Disconnect all events created by this widget."""
|
|
for c in self.cids:
|
|
self.image_viewer.disconnect_event(c)
|
|
|
|
def remove_image_artists(self):
|
|
"""Disconnect artists that are connected to the image viewer."""
|
|
for a in self.artists:
|
|
self.image_viewer.remove_artist(a)
|