2 #---------------------------------------------------------------------- 
   4 class PyOnDemandOutputWindow
: 
   6     A class that can be used for redirecting Python's stdout and 
   7     stderr streams.  It will do nothing until something is wrriten to 
   8     the stream at which point it will create a Frame with a text area 
   9     and write the text there. 
  11     def __init__(self
, title 
= "wxPython: stdout/stderr"): 
  14         self
.pos    
= wx
.DefaultPosition
 
  15         self
.size   
= (450, 300) 
  18     def SetParent(self
, parent
): 
  19         """Set the window to be used as the popup Frame's parent.""" 
  23     def CreateOutputWindow(self
, st
): 
  24         self
.frame 
= wx
.Frame(self
.parent
, -1, self
.title
, self
.pos
, self
.size
, 
  25                               style
=wx
.DEFAULT_FRAME_STYLE
) 
  26         self
.text  
= wx
.TextCtrl(self
.frame
, -1, "", 
  27                                  style
=wx
.TE_MULTILINE|wx
.TE_READONLY
) 
  28         self
.text
.AppendText(st
) 
  30         self
.frame
.Bind(wx
.EVT_CLOSE
, self
.OnCloseWindow
) 
  33     def OnCloseWindow(self
, event
): 
  34         if self
.frame 
is not None: 
  40     # These methods provide the file-like output behaviour. 
  41     def write(self
, text
): 
  43         Create the output window if needed and write the string to it. 
  44         If not called in the context of the gui thread then uses 
  45         CallAfter to do the work there. 
  47         if self
.frame 
is None: 
  48             if not wx
.Thread_IsMain(): 
  49                 wx
.CallAfter(self
.CreateOutputWindow
, text
) 
  51                 self
.CreateOutputWindow(text
) 
  53             if not wx
.Thread_IsMain(): 
  54                 wx
.CallAfter(self
.text
.AppendText
, text
) 
  56                 self
.text
.AppendText(text
) 
  60         if self
.frame 
is not None: 
  61             wx
.CallAfter(self
.frame
.Close
) 
  69 #---------------------------------------------------------------------- 
  71 _defRedirect 
= (wx
.Platform 
== '__WXMSW__' or wx
.Platform 
== '__WXMAC__') 
  75     The ``wx.App`` class represents the application and is used to: 
  77       * bootstrap the wxPython system and initialize the underlying 
  79       * set and get application-wide properties 
  80       * implement the windowing system main message or event loop, 
  81         and to dispatch events to window instances 
  84     Every application must have a ``wx.App`` instance, and all 
  85     creation of UI objects should be delayed until after the 
  86     ``wx.App`` object has been created in order to ensure that the gui 
  87     platform and wxWidgets have been fully initialized. 
  89     Normally you would derive from this class and implement an 
  90     ``OnInit`` method that creates a frame and then calls 
  91     ``self.SetTopWindow(frame)``. 
  93     :see: `wx.PySimpleApp` for a simpler app class that can be used 
  97     outputWindowClass 
= PyOnDemandOutputWindow
 
  99     def __init__(self
, redirect
=_defRedirect
, filename
=None, 
 100                  useBestVisual
=False, clearSigInt
=True): 
 102         Construct a ``wx.App`` object.   
 104         :param redirect: Should ``sys.stdout`` and ``sys.stderr`` be 
 105             redirected?  Defaults to True on Windows and Mac, False 
 106             otherwise.  If ``filename`` is None then output will be 
 107             redirected to a window that pops up as needed.  (You can 
 108             control what kind of window is created for the output by 
 109             resetting the class variable ``outputWindowClass`` to a 
 110             class of your choosing.) 
 112         :param filename: The name of a file to redirect output to, if 
 115         :param useBestVisual: Should the app try to use the best 
 116             available visual provided by the system (only relevant on 
 117             systems that have more than one visual.)  This parameter 
 118             must be used instead of calling `SetUseBestVisual` later 
 119             on because it must be set before the underlying GUI 
 120             toolkit is initialized. 
 122         :param clearSigInt: Should SIGINT be cleared?  This allows the 
 123             app to terminate upon a Ctrl-C in the console like other 
 126         :note: You should override OnInit to do applicaition 
 127             initialization to ensure that the system, toolkit and 
 128             wxWidgets are fully initialized. 
 131         wx
.PyApp
.__init
__(self
) 
 133         # make sure we can create a GUI 
 134         if not self
.IsDisplayAvailable(): 
 136             if wx
.Platform 
== "__WXMAC__": 
 137                 msg 
= """This program needs access to the screen. 
 138 Please run with 'pythonw', not 'python', and only when you are logged 
 139 in on the main display of your Mac.""" 
 141             elif wx
.Platform 
== "__WXGTK__": 
 142                 msg 
="Unable to access the X Display, is $DISPLAY set properly?" 
 145                 msg 
= "Unable to create GUI" 
 146                 # TODO: more description is needed for wxMSW... 
 148             raise SystemExit(msg
) 
 150         # This has to be done before OnInit 
 151         self
.SetUseBestVisual(useBestVisual
) 
 153         # Set the default handler for SIGINT.  This fixes a problem 
 154         # where if Ctrl-C is pressed in the console that started this 
 155         # app then it will not appear to do anything, (not even send 
 156         # KeyboardInterrupt???)  but will later segfault on exit.  By 
 157         # setting the default handler then the app will exit, as 
 158         # expected (depending on platform.) 
 162                 signal
.signal(signal
.SIGINT
, signal
.SIG_DFL
) 
 166         # Save and redirect the stdio to a window? 
 168         self
.saveStdio 
= (_sys
.stdout
, _sys
.stderr
) 
 170             self
.RedirectStdio(filename
) 
 172         # Use Python's install prefix as the default   
 173         wx
.StandardPaths
.Get().SetInstallPrefix(_sys
.prefix
) 
 175         # Until the new native control for wxMac is up to par, still use the generic one. 
 176         wx
.SystemOptions
.SetOptionInt("mac.listctrl.always_use_generic", 1) 
 178         # This finishes the initialization of wxWindows and then calls 
 179         # the OnInit that should be present in the derived class 
 185         Things that must be done after _BootstrapApp has done its 
 186         thing, but would be nice if they were already done by the time 
 187         that OnInit is called. 
 189         wx
.StockGDI
._initStockObjects
() 
 192     def __del__(self
, destroy
=wx
.PyApp
.__del
__): 
 193         self
.RestoreStdio()  # Just in case the MainLoop was overridden 
 198         wx
.PyApp
.Destroy(self
) 
 200     def SetTopWindow(self
, frame
): 
 201         """Set the \"main\" top level window""" 
 203             self
.stdioWin
.SetParent(frame
) 
 204         wx
.PyApp
.SetTopWindow(self
, frame
) 
 208         """Execute the main GUI event loop""" 
 209         wx
.PyApp
.MainLoop(self
) 
 213     def RedirectStdio(self
, filename
=None): 
 214         """Redirect sys.stdout and sys.stderr to a file or a popup window.""" 
 216             _sys
.stdout 
= _sys
.stderr 
= open(filename
, 'a') 
 218             self
.stdioWin 
= self
.outputWindowClass() 
 219             _sys
.stdout 
= _sys
.stderr 
= self
.stdioWin
 
 222     def RestoreStdio(self
): 
 224             _sys
.stdout
, _sys
.stderr 
= self
.saveStdio
 
 229     def SetOutputWindowAttributes(self
, title
=None, pos
=None, size
=None): 
 231         Set the title, position and/or size of the output window if 
 232         the stdio has been redirected.  This should be called before 
 233         any output would cause the output window to be created. 
 236             if title 
is not None: 
 237                 self
.stdioWin
.title 
= title
 
 239                 self
.stdioWin
.pos 
= pos
 
 241                 self
.stdioWin
.size 
= size
 
 246 # change from wx.PyApp_XX to wx.App_XX 
 247 App_GetMacSupportPCMenuShortcuts 
= _core_
.PyApp_GetMacSupportPCMenuShortcuts
 
 248 App_GetMacAboutMenuItemId        
= _core_
.PyApp_GetMacAboutMenuItemId
 
 249 App_GetMacPreferencesMenuItemId  
= _core_
.PyApp_GetMacPreferencesMenuItemId
 
 250 App_GetMacExitMenuItemId         
= _core_
.PyApp_GetMacExitMenuItemId
 
 251 App_GetMacHelpMenuTitleName      
= _core_
.PyApp_GetMacHelpMenuTitleName
 
 252 App_SetMacSupportPCMenuShortcuts 
= _core_
.PyApp_SetMacSupportPCMenuShortcuts
 
 253 App_SetMacAboutMenuItemId        
= _core_
.PyApp_SetMacAboutMenuItemId
 
 254 App_SetMacPreferencesMenuItemId  
= _core_
.PyApp_SetMacPreferencesMenuItemId
 
 255 App_SetMacExitMenuItemId         
= _core_
.PyApp_SetMacExitMenuItemId
 
 256 App_SetMacHelpMenuTitleName      
= _core_
.PyApp_SetMacHelpMenuTitleName
 
 257 App_GetComCtl32Version           
= _core_
.PyApp_GetComCtl32Version
 
 259 #---------------------------------------------------------------------------- 
 261 class PySimpleApp(wx
.App
): 
 263     A simple application class.  You can just create one of these and 
 264     then then make your top level windows later, and not have to worry 
 265     about OnInit.  For example:: 
 267         app = wx.PySimpleApp() 
 268         frame = wx.Frame(None, title='Hello World') 
 275     def __init__(self
, redirect
=False, filename
=None, 
 276                  useBestVisual
=False, clearSigInt
=True): 
 278         :see: `wx.App.__init__` 
 280         wx
.App
.__init
__(self
, redirect
, filename
, useBestVisual
, clearSigInt
) 
 287 # Is anybody using this one? 
 288 class PyWidgetTester(wx
.App
): 
 289     def __init__(self
, size 
= (250, 100)): 
 291         wx
.App
.__init
__(self
, 0) 
 294         self
.frame 
= wx
.Frame(None, -1, "Widget Tester", pos
=(0,0), size
=self
.size
) 
 295         self
.SetTopWindow(self
.frame
) 
 298     def SetWidget(self
, widgetClass
, *args
, **kwargs
): 
 299         w 
= widgetClass(self
.frame
, *args
, **kwargs
) 
 300         self
.frame
.Show(True) 
 302 #---------------------------------------------------------------------------- 
 303 # DO NOT hold any other references to this object.  This is how we 
 304 # know when to cleanup system resources that wxWidgets is holding.  When 
 305 # the sys module is unloaded, the refcount on sys.__wxPythonCleanup 
 306 # goes to zero and it calls the wx.App_CleanUp function. 
 310         self
.cleanup 
= _core_
.App_CleanUp
 
 314 _sys
.__wxPythonCleanup 
= __wxPyCleanup() 
 316 ## # another possible solution, but it gets called too early... 
 318 ## atexit.register(_core_.wxApp_CleanUp) 
 321 #----------------------------------------------------------------------------