From 6f18eed4e0c7fdd2a1a8eaf43a069286e6e39051 Mon Sep 17 00:00:00 2001 From: sccolbert Date: Mon, 2 Nov 2009 18:42:12 +0100 Subject: [PATCH] cleaned up the window manager, and modified the qt-plugin to use it. also changed the order of try: except: when trying to load the plugins, to make sure that one gui toolkit doesnt trample the pyos_input hook of the other. --- scikits/image/io/_plugins/gtk_plugin.py | 82 ++++++++++++---------- scikits/image/io/_plugins/qt_plugin.py | 93 +++++++++++++------------ scikits/image/io/_plugins/util.py | 36 ++++++++-- 3 files changed, 126 insertions(+), 85 deletions(-) diff --git a/scikits/image/io/_plugins/gtk_plugin.py b/scikits/image/io/_plugins/gtk_plugin.py index d6619d3d..0214c179 100644 --- a/scikits/image/io/_plugins/gtk_plugin.py +++ b/scikits/image/io/_plugins/gtk_plugin.py @@ -1,53 +1,61 @@ -from util import prepare_for_display, window_manager +from util import prepare_for_display, window_manager, GuiLockError import plugin try: - import gtk -except ImportError: - pass + # we try to aquire the gui lock first + # or else the gui import might trample another + # gui's pyos_inputhook. + window_manager.acquire('gtk') +except GuiLockError, gle: + print gle else: + try: + import gtk + except ImportError: + print 'pygtk libraries not installed.' + print 'plugin not loaded.' + window_manager._release('gtk') + else: - window_manager.acquire() + class ImageWindow(gtk.Window): + def __init__(self, arr, mgr): + gtk.Window.__init__(self) + self.mgr = mgr + self.mgr.add_window(self) - class ImageWindow(gtk.Window): - def __init__(self, arr, mgr): - gtk.Window.__init__(self) - self.mgr = mgr - self.mgr.add_window(self) + self.connect("destroy", self.destroy) - self.connect("destroy", self.destroy) + width = arr.shape[1] + height = arr.shape[0] + rstride = arr.strides[0] + pb = gtk.gdk.pixbuf_new_from_data(arr.data, + gtk.gdk.COLORSPACE_RGB, + False, 8, width, height, + rstride) + self.img = gtk.Image() + self.img.set_from_pixbuf(pb) - width = arr.shape[1] - height = arr.shape[0] - rstride = arr.strides[0] - pb = gtk.gdk.pixbuf_new_from_data(arr.data, gtk.gdk.COLORSPACE_RGB, - False, 8, width, height, rstride) - self.img = gtk.Image() - self.img.set_from_pixbuf(pb) + self.add(self.img) + self.img.show() - self.add(self.img) - self.img.show() + def destroy(self, widget, data=None): + self.mgr.remove_window(self) - def destroy(self, widget, data=None): - self.mgr.remove_window(self) + def gtk_imshow(arr): + arr = prepare_for_display(arr) - def all_gone(): - print 'all windows destroyed' + iw = ImageWindow(arr, window_manager) + iw.show() - def gtk_imshow(arr): - arr = prepare_for_display(arr) - - iw = ImageWindow(arr, window_manager) - iw.show() - - def gtk_show(): - if window_manager.has_images(): - window_manager.register_callback(gtk.main_quit) - gtk.main() - else: - print 'no images to display' + def gtk_show(): + if window_manager.has_images(): + window_manager.register_callback(gtk.main_quit) + gtk.main() + else: + print 'no images to display' - plugin.register('gtk', show=gtk_imshow, appshow=gtk_show) + plugin.register('gtk', show=gtk_imshow, appshow=gtk_show) + diff --git a/scikits/image/io/_plugins/qt_plugin.py b/scikits/image/io/_plugins/qt_plugin.py index 01908b2a..9bee26b7 100644 --- a/scikits/image/io/_plugins/qt_plugin.py +++ b/scikits/image/io/_plugins/qt_plugin.py @@ -1,66 +1,73 @@ import plugin -from util import prepare_for_display +from util import prepare_for_display, window_manager, GuiLockError import numpy as np import sys -app = None -windows = [] try: - from PyQt4.QtGui import (QApplication, QMainWindow, QImage, QPixmap, - QLabel) -except ImportError: - pass + # we try to aquire the gui lock first + # or else the gui import might trample another + # gui's pyos_inputhook. + window_manager.acquire('qt') + +except GuiLockError, gle: + print gle + else: + try: + from PyQt4.QtGui import (QApplication, QMainWindow, QImage, QPixmap, + QLabel) - class ImageWindow(QMainWindow): - def __init__(self, arr): - QMainWindow.__init__(self) + except ImportError: + print 'pyqt4 libraries not installed.' + print 'plugin not loaded' + window_manager._release('qt') - img = QImage(arr.data, arr.shape[1], arr.shape[0], - QImage.Format_RGB888) - pm = QPixmap.fromImage(img) + else: - label = QLabel() - label.setPixmap(pm) - label.show() + app = None - self.label = label - self.setCentralWidget(self.label) + class ImageWindow(QMainWindow): + def __init__(self, arr, mgr): + QMainWindow.__init__(self) + self.mgr = mgr + img = QImage(arr.data, arr.shape[1], arr.shape[0], + QImage.Format_RGB888) + pm = QPixmap.fromImage(img) - def closeEvent(self, event): - # Allow window to be destroyed by removing any - # references to it - windows.remove(self) + label = QLabel() + label.setPixmap(pm) + label.show() - def show(arr, block=True): - global app + self.label = label + self.setCentralWidget(self.label) + self.mgr.add_window(self) - if not '-qt4thread' in sys.argv and app is None: - app = QApplication([]) + def closeEvent(self, event): + # Allow window to be destroyed by removing any + # references to it + self.mgr.remove_window(self) - arr = prepare_for_display(arr) + def qt_imshow(arr, block=True): + global app - iw = ImageWindow(arr) - iw.show() + if not app: + app = QApplication([]) - # Keep track of window so that it doesn't get destroyed - windows.append(iw) + arr = prepare_for_display(arr) - if app and block: - app.exec_() + iw = ImageWindow(arr, window_manager) + iw.show() - plugin.register('qt', show=show) + def qt_show(): + global app + if app and window_manager.has_images(): + app.exec_() + else: + print 'no images to show' + + plugin.register('qt', show=qt_imshow, appshow=qt_show) -if __name__ == "__main__": - import scikits.image.io as io - io.plugin.use('qt', 'show') - img = np.empty((200, 200, 3), dtype=np.uint8) - img[:50, :50, 0] = 100 - img[25:100, 25:100, 1] = 200 - img[:, :, 2] = 155 - io.imshow(img, block=False) - io.imshow(img) diff --git a/scikits/image/io/_plugins/util.py b/scikits/image/io/_plugins/util.py index f6e9e921..9b0de15d 100644 --- a/scikits/image/io/_plugins/util.py +++ b/scikits/image/io/_plugins/util.py @@ -2,6 +2,14 @@ import numpy as np # utilities to make life easier for plugin writers. + +class GuiLockError(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return self.msg + class WindowManager(object): ''' A class to keep track of spawned windows, and make any needed callback once all the windows, @@ -12,22 +20,40 @@ class WindowManager(object): self._callback_args = () self._callback_kwargs = {} self._gui_lock = False + self._guikit = '' def _check_locked(self): if not self._gui_lock: - raise RuntimeError(\ - 'Must first acquire the gui lock before using this image manager ') + raise GuiLockError(\ + 'Must first acquire the gui lock before using this image manager') def _exec_callback(self): if self._callback: self._callback(*self._callback_args, **self._callback_kwargs) - def acquire(self): + def acquire(self, kit): if self._gui_lock: - raise RuntimeError(\ - 'The gui lock can only be acquired by one toolkit per session') + raise GuiLockError(\ + 'The gui lock can only be acquired by one toolkit per session. \ + The lock is already aquired by %s' % self._guikit) else: self._gui_lock = True + self._guikit = str(kit) + + def _release(self, kit): + # releaseing the lock will lose all references to currently + # track images and callback. + # this function is private for reason! + self._check_locked() + if str(kit) == self._guikit: + self._windows = [] + self._callback = None + self._callback_args = () + self._callback_kwargs = {} + self._gui_lock = False + self._guikit = '' + else: + raise RuntimeError('Only the toolkit that owns the lock may release it') def add_window(self, win): self._check_locked()