def __init__(self, **traits): """ Initialize the Qt server. This simply configures the widget to serve the Python model. """ # This statement makes sure that when we dispatch traits events on the # 'ui' thread, it passes on those events through the Qt layer. set_ui_handler(ui_handler) super(QtServer, self).__init__(**traits) self.webview.setUrl(self.home_url) self._enable_qwidget_embedding() return
Created on Jan 4, 2018 @author: brian ''' # select the 'null' pyface toolkit. an exception is raised if the qt toolkit # is subsequently imported, but that's better than trying to actually create # a Qt app if PyQt is accidentally imported. from traits.etsconfig.api import ETSConfig ETSConfig.toolkit = 'null' # even so, sometimes events get dispatched to the UI handler. # make sure they go into a black hole from traits.trait_notifiers import set_ui_handler set_ui_handler(lambda *x, **y: None) # use the sphinx autodoc module-mocker to mock out traitsui.qt4 # because when it's imported, it starts a Qt Application from cytoflowgui.tests.sphinx_mock import MockFinder import sys sys.meta_path.insert(0, MockFinder(['traitsui.qt4'])) # make sure that even if we're running locally, we're using the Agg output import matplotlib matplotlib.use("Agg") import unittest, multiprocessing, os, logging from logging.handlers import QueueHandler, QueueListener
def _finished(self): """ Remove the call from the list, so it can be garbage collected. """ self._calls_mutex.lock() del self._calls[self._calls.index(self)] self._calls_mutex.unlock() def ui_handler(handler, *args, **kwds): """ Handles UI notification handler requests that occur on a thread other than the UI thread. """ _CallAfter(handler, *args, **kwds) # Tell the traits notification handlers to use this UI handler set_ui_handler(ui_handler) #------------------------------------------------------------------------- # 'GUIToolkit' class: #------------------------------------------------------------------------- class GUIToolkit(Toolkit): """ Implementation class for PyQt toolkit. """ #------------------------------------------------------------------------- # Create PyQt specific user interfaces using information from the # specified UI object: #------------------------------------------------------------------------- def ui_panel(self, ui, parent):
import wx from traits.trait_notifiers import set_ui_handler, ui_handler from pyface.base_toolkit import Toolkit from .gui import GUI # Check the version number is late enough. if wx.VERSION < (2, 8): raise RuntimeError("Need wx version 2.8 or higher, but got %s" % str(wx.VERSION)) # It's possible that it has already been initialised. _app = wx.GetApp() if _app is None: _app = wx.App() # stop logging to a modal window by default # (apps can override by setting a different active target) _log = wx.LogStderr() wx.Log.SetActiveTarget(_log) # create the toolkit object toolkit_object = Toolkit('pyface', 'wx', 'pyface.ui.wx') # ensure that Traits has a UI handler appropriate for the toolkit. if ui_handler is None: # Tell the traits notification handlers to use this UI handler set_ui_handler(GUI.invoke_later)
def init_traitsui_handler(): ''' Setup handler for traits notification in Qt GUI. This function needs to be called before using traits notification which trigger GUI modification from non-principal threads. **WARNING**: depending on the Qt bindings (PyQt or PySide), this function may instantiate a QApplication. It seems that when using PyQt4, QApplication is not instantiated, whereas when using PySide, it is. This means that after this function has been called, one must check if the application has been created before recreating it: :: app = QtGui.QApplication.instance() if not app: app = QtGui.QApplication(sys.argv) This behaviour is triggered somewhere in the traitsui.qt4.toolkit module, we cannot change it easily. ''' global traits_ui_handler_initialized from . import QtCore, QtGui if traits_ui_handler_initialized: return # already done try: if get_qt_backend() in ('PyQt4', 'PySide'): from traitsui.qt4 import toolkit else: # if using Qt5 we must not import traitsui.qt4, which would cause # a crash. Then use the code taken from traitsui.qt4.toolkit # in a qt-independent manner raise ImportError('traitsui doesn\'t provide a PyQt5 backend') except Exception: # copy of the code from traitsui.qt4.toolkit from traits.trait_notifiers import set_ui_handler #------------------------------------------------------------------------------- # Handles UI notification handler requests that occur on a thread other than # the UI thread: #------------------------------------------------------------------------------- _QT_TRAITS_EVENT = QtCore.QEvent.Type( QtCore.QEvent.registerEventType()) class _CallAfter(QtCore.QObject): """ This class dispatches a handler so that it executes in the main GUI thread (similar to the wx function). """ # The list of pending calls. _calls = [] # The mutex around the list of pending calls. _calls_mutex = QtCore.QMutex() def __init__(self, handler, *args, **kwds): """ Initialise the call. """ QtCore.QObject.__init__(self) # Save the details of the call. self._handler = handler self._args = args self._kwds = kwds # Add this to the list. self._calls_mutex.lock() self._calls.append(self) self._calls_mutex.unlock() # Move to the main GUI thread. self.moveToThread(QtGui.QApplication.instance().thread()) # Post an event to be dispatched on the main GUI thread. Note that # we do not call QTimer.singleShot, which would be simpler, because # that only works on QThreads. We want regular Python threads to work. event = QtCore.QEvent(_QT_TRAITS_EVENT) QtGui.QApplication.instance().postEvent(self, event) def event(self, event): """ QObject event handler. """ if event.type() == _QT_TRAITS_EVENT: # Invoke the handler self._handler(*self._args, **self._kwds) # We cannot remove from self._calls here. QObjects don't like being # garbage collected during event handlers (there are tracebacks, # plus maybe a memory leak, I think). QtCore.QTimer.singleShot(0, self._finished) return True else: return QtCore.QObject.event(self, event) def _finished(self): """ Remove the call from the list, so it can be garbage collected. """ self._calls_mutex.lock() del self._calls[self._calls.index(self)] self._calls_mutex.unlock() def ui_handler(handler, *args, **kwds): """ Handles UI notification handler requests that occur on a thread other than the UI thread. """ _CallAfter(handler, *args, **kwds) # Tell the traits notification handlers to use this UI handler set_ui_handler(ui_handler)
from .gui import GUI # Check the version number is late enough. if wx.VERSION < (2, 8): raise RuntimeError( "Need wx version 2.8 or higher, but got %s" % str(wx.VERSION) ) # It's possible that it has already been initialised. _app = wx.GetApp() if _app is None: _app = wx.App() # stop logging to a modal window by default # (apps can override by setting a different active target) _log = wx.LogStderr() wx.Log.SetActiveTarget(_log) # create the toolkit object toolkit_object = Toolkit('pyface', 'wx', 'pyface.ui.wx') # ensure that Traits has a UI handler appropriate for the toolkit. if ui_handler is None: # Tell the traits notification handlers to use this UI handler set_ui_handler(GUI.invoke_later)