Add infrastructure for conneting plugin output to a viewer.

This commit is contained in:
Tony S Yu
2013-05-28 23:52:10 -05:00
parent e7ca4b6138
commit bd860b7720
2 changed files with 42 additions and 12 deletions
+19 -2
View File
@@ -1,9 +1,12 @@
"""
Base class for Plugins that interact with ImageViewer.
"""
from ..qt import QtGui
from ..qt.QtCore import Qt
from warnings import warn
import numpy as np
from ..qt import QtGui
from ..qt.QtCore import Qt, pyqtSignal
from ..utils import RequiredAttr, init_qtapp
@@ -71,6 +74,10 @@ class Plugin(QtGui.QDialog):
name = 'Plugin'
image_viewer = RequiredAttr("%s is not attached to ImageViewer" % name)
# Signals used when viewers are linked to the Plugin output.
image_updated = pyqtSignal(np.ndarray)
_started = pyqtSignal()
def __init__(self, image_filter=None, height=0, width=400, useblit=True):
init_qtapp()
super(Plugin, self).__init__()
@@ -79,6 +86,9 @@ class Plugin(QtGui.QDialog):
# If subclass defines `image_filter` method ignore input.
if not hasattr(self, 'image_filter'):
self.image_filter = image_filter
elif image_filter is not None:
warn("If the Plugin class defines an `image_filter` method, "
"then the `image_filter` argument is ignored.")
self.setWindowTitle(self.name)
self.layout = QtGui.QGridLayout(self)
@@ -155,7 +165,9 @@ class Plugin(QtGui.QDialog):
kwargs = dict([(name, self._get_value(a))
for name, a in self.keyword_arguments.iteritems()])
filtered = self.image_filter(*arguments, **kwargs)
self.display_filtered_image(filtered)
self.image_updated.emit(filtered)
def _get_value(self, param):
# If param is a widget, return its `val` attribute.
@@ -183,6 +195,11 @@ class Plugin(QtGui.QDialog):
"""
setattr(self, name, value)
def show(self, main_window=True):
"""Show plugin."""
super(Plugin, self).show()
self._started.emit()
def closeEvent(self, event):
"""On close disconnect all artists and events from ImageViewer.
+23 -10
View File
@@ -11,6 +11,7 @@ import numpy as np
from .. import utils
from ..widgets import Slider
from ..utils import dialogs
from ..plugins.base import Plugin
__all__ = ['ImageViewer', 'CollectionViewer']
@@ -81,6 +82,13 @@ class ImageViewer(QtGui.QMainWindow):
self.main_widget = QtGui.QWidget()
self.setCentralWidget(self.main_widget)
if isinstance(image, Plugin):
plugin = image
image = plugin.filtered_image
plugin.image_updated.connect(self._new_original_image)
# When plugin is started, start
plugin._started.connect(self._show)
self.fig, self.ax = utils.figimage(image)
self.canvas = self.fig.canvas
self.canvas.setParent(self)
@@ -88,9 +96,7 @@ class ImageViewer(QtGui.QMainWindow):
self.ax.autoscale(enable=False)
self._image_plot = self.ax.images[0]
self.original_image = image
self.image = image.copy()
self._new_original_image(image)
self.plugins = []
self.layout = QtGui.QVBoxLayout(self.main_widget)
@@ -115,8 +121,11 @@ class ImageViewer(QtGui.QMainWindow):
if filename is None:
return
image = io.imread(filename)
self._new_original_image(image)
def _new_original_image(self, image):
self.original_image = image # update saved image
self.image = image # update displayed image
self.image = image.copy() # update displayed image
def save_to_file(self):
"""Save current image to file.
@@ -160,16 +169,20 @@ class ImageViewer(QtGui.QMainWindow):
p.move(w, y)
y += p.geometry().height()
def show(self):
"""Show ImageViewer and attached plugins.
This behaves much like `matplotlib.pyplot.show` and `QWidget.show`.
"""
def _show(self):
self.auto_layout()
for p in self.plugins:
p.show()
super(ImageViewer, self).show()
utils.start_qtapp()
def show(self, main_window=True):
"""Show ImageViewer and attached plugins.
This behaves much like `matplotlib.pyplot.show` and `QWidget.show`.
"""
self._show()
if main_window:
utils.start_qtapp()
def redraw(self):
self.canvas.draw_idle()