$search
00001 00002 #---------------------------------------------------------------------- 00003 00004 class PyOnDemandOutputWindow: 00005 """ 00006 A class that can be used for redirecting Python's stdout and 00007 stderr streams. It will do nothing until something is wrriten to 00008 the stream at which point it will create a Frame with a text area 00009 and write the text there. 00010 """ 00011 def __init__(self, title = "wxPython: stdout/stderr"): 00012 self.frame = None 00013 self.title = title 00014 self.pos = wx.DefaultPosition 00015 self.size = (450, 300) 00016 self.parent = None 00017 00018 def SetParent(self, parent): 00019 """Set the window to be used as the popup Frame's parent.""" 00020 self.parent = parent 00021 00022 00023 def CreateOutputWindow(self, st): 00024 self.frame = wx.Frame(self.parent, -1, self.title, self.pos, self.size, 00025 style=wx.DEFAULT_FRAME_STYLE) 00026 self.text = wx.TextCtrl(self.frame, -1, "", 00027 style=wx.TE_MULTILINE|wx.TE_READONLY) 00028 self.text.AppendText(st) 00029 self.frame.Show(True) 00030 self.frame.Bind(wx.EVT_CLOSE, self.OnCloseWindow) 00031 00032 00033 def OnCloseWindow(self, event): 00034 if self.frame is not None: 00035 self.frame.Destroy() 00036 self.frame = None 00037 self.text = None 00038 00039 00040 # These methods provide the file-like output behaviour. 00041 def write(self, text): 00042 """ 00043 Create the output window if needed and write the string to it. 00044 If not called in the context of the gui thread then uses 00045 CallAfter to do the work there. 00046 """ 00047 if self.frame is None: 00048 if not wx.Thread_IsMain(): 00049 wx.CallAfter(self.CreateOutputWindow, text) 00050 else: 00051 self.CreateOutputWindow(text) 00052 else: 00053 if not wx.Thread_IsMain(): 00054 wx.CallAfter(self.text.AppendText, text) 00055 else: 00056 self.text.AppendText(text) 00057 00058 00059 def close(self): 00060 if self.frame is not None: 00061 wx.CallAfter(self.frame.Close) 00062 00063 00064 def flush(self): 00065 pass 00066 00067 00068 00069 #---------------------------------------------------------------------- 00070 00071 _defRedirect = (wx.Platform == '__WXMSW__' or wx.Platform == '__WXMAC__') 00072 00073 class App(wx.PyApp): 00074 """ 00075 The ``wx.App`` class represents the application and is used to: 00076 00077 * bootstrap the wxPython system and initialize the underlying 00078 gui toolkit 00079 * set and get application-wide properties 00080 * implement the windowing system main message or event loop, 00081 and to dispatch events to window instances 00082 * etc. 00083 00084 Every application must have a ``wx.App`` instance, and all 00085 creation of UI objects should be delayed until after the 00086 ``wx.App`` object has been created in order to ensure that the gui 00087 platform and wxWidgets have been fully initialized. 00088 00089 Normally you would derive from this class and implement an 00090 ``OnInit`` method that creates a frame and then calls 00091 ``self.SetTopWindow(frame)``. 00092 00093 :see: `wx.PySimpleApp` for a simpler app class that can be used 00094 directly. 00095 """ 00096 00097 outputWindowClass = PyOnDemandOutputWindow 00098 00099 def __init__(self, redirect=_defRedirect, filename=None, 00100 useBestVisual=False, clearSigInt=True): 00101 """ 00102 Construct a ``wx.App`` object. 00103 00104 :param redirect: Should ``sys.stdout`` and ``sys.stderr`` be 00105 redirected? Defaults to True on Windows and Mac, False 00106 otherwise. If `filename` is None then output will be 00107 redirected to a window that pops up as needed. (You can 00108 control what kind of window is created for the output by 00109 resetting the class variable ``outputWindowClass`` to a 00110 class of your choosing.) 00111 00112 :param filename: The name of a file to redirect output to, if 00113 redirect is True. 00114 00115 :param useBestVisual: Should the app try to use the best 00116 available visual provided by the system (only relevant on 00117 systems that have more than one visual.) This parameter 00118 must be used instead of calling `SetUseBestVisual` later 00119 on because it must be set before the underlying GUI 00120 toolkit is initialized. 00121 00122 :param clearSigInt: Should SIGINT be cleared? This allows the 00123 app to terminate upon a Ctrl-C in the console like other 00124 GUI apps will. 00125 00126 :note: You should override OnInit to do applicaition 00127 initialization to ensure that the system, toolkit and 00128 wxWidgets are fully initialized. 00129 """ 00130 00131 wx.PyApp.__init__(self) 00132 00133 # make sure we can create a GUI 00134 if not self.IsDisplayAvailable(): 00135 00136 if wx.Platform == "__WXMAC__": 00137 msg = """This program needs access to the screen. 00138 Please run with 'pythonw', not 'python', and only when you are logged 00139 in on the main display of your Mac.""" 00140 00141 elif wx.Platform == "__WXGTK__": 00142 msg ="Unable to access the X Display, is $DISPLAY set properly?" 00143 00144 else: 00145 msg = "Unable to create GUI" 00146 # TODO: more description is needed for wxMSW... 00147 00148 raise SystemExit(msg) 00149 00150 # This has to be done before OnInit 00151 self.SetUseBestVisual(useBestVisual) 00152 00153 # Set the default handler for SIGINT. This fixes a problem 00154 # where if Ctrl-C is pressed in the console that started this 00155 # app then it will not appear to do anything, (not even send 00156 # KeyboardInterrupt???) but will later segfault on exit. By 00157 # setting the default handler then the app will exit, as 00158 # expected (depending on platform.) 00159 if clearSigInt: 00160 try: 00161 import signal 00162 signal.signal(signal.SIGINT, signal.SIG_DFL) 00163 except: 00164 pass 00165 00166 # Save and redirect the stdio to a window? 00167 self.stdioWin = None 00168 self.saveStdio = (_sys.stdout, _sys.stderr) 00169 if redirect: 00170 self.RedirectStdio(filename) 00171 00172 # Use Python's install prefix as the default 00173 wx.StandardPaths.Get().SetInstallPrefix(_sys.prefix) 00174 00175 # Until the new native control for wxMac is up to par, still use the generic one. 00176 wx.SystemOptions.SetOptionInt("mac.listctrl.always_use_generic", 1) 00177 00178 # This finishes the initialization of wxWindows and then calls 00179 # the OnInit that should be present in the derived class 00180 self._BootstrapApp() 00181 00182 00183 def OnPreInit(self): 00184 """ 00185 Things that must be done after _BootstrapApp has done its 00186 thing, but would be nice if they were already done by the time 00187 that OnInit is called. 00188 """ 00189 wx.StockGDI._initStockObjects() 00190 00191 00192 def __del__(self, destroy=wx.PyApp.__del__): 00193 self.RestoreStdio() # Just in case the MainLoop was overridden 00194 destroy(self) 00195 00196 def Destroy(self): 00197 self.this.own(False) 00198 wx.PyApp.Destroy(self) 00199 00200 def SetTopWindow(self, frame): 00201 """Set the \"main\" top level window""" 00202 if self.stdioWin: 00203 self.stdioWin.SetParent(frame) 00204 wx.PyApp.SetTopWindow(self, frame) 00205 00206 00207 def MainLoop(self): 00208 """Execute the main GUI event loop""" 00209 wx.PyApp.MainLoop(self) 00210 self.RestoreStdio() 00211 00212 00213 def RedirectStdio(self, filename=None): 00214 """Redirect sys.stdout and sys.stderr to a file or a popup window.""" 00215 if filename: 00216 _sys.stdout = _sys.stderr = open(filename, 'a') 00217 else: 00218 self.stdioWin = self.outputWindowClass() 00219 _sys.stdout = _sys.stderr = self.stdioWin 00220 00221 00222 def RestoreStdio(self): 00223 try: 00224 _sys.stdout, _sys.stderr = self.saveStdio 00225 except: 00226 pass 00227 00228 00229 def SetOutputWindowAttributes(self, title=None, pos=None, size=None): 00230 """ 00231 Set the title, position and/or size of the output window if 00232 the stdio has been redirected. This should be called before 00233 any output would cause the output window to be created. 00234 """ 00235 if self.stdioWin: 00236 if title is not None: 00237 self.stdioWin.title = title 00238 if pos is not None: 00239 self.stdioWin.pos = pos 00240 if size is not None: 00241 self.stdioWin.size = size 00242 00243 00244 00245 00246 # change from wx.PyApp_XX to wx.App_XX 00247 App_GetMacSupportPCMenuShortcuts = _core_.PyApp_GetMacSupportPCMenuShortcuts 00248 App_GetMacAboutMenuItemId = _core_.PyApp_GetMacAboutMenuItemId 00249 App_GetMacPreferencesMenuItemId = _core_.PyApp_GetMacPreferencesMenuItemId 00250 App_GetMacExitMenuItemId = _core_.PyApp_GetMacExitMenuItemId 00251 App_GetMacHelpMenuTitleName = _core_.PyApp_GetMacHelpMenuTitleName 00252 App_SetMacSupportPCMenuShortcuts = _core_.PyApp_SetMacSupportPCMenuShortcuts 00253 App_SetMacAboutMenuItemId = _core_.PyApp_SetMacAboutMenuItemId 00254 App_SetMacPreferencesMenuItemId = _core_.PyApp_SetMacPreferencesMenuItemId 00255 App_SetMacExitMenuItemId = _core_.PyApp_SetMacExitMenuItemId 00256 App_SetMacHelpMenuTitleName = _core_.PyApp_SetMacHelpMenuTitleName 00257 App_GetComCtl32Version = _core_.PyApp_GetComCtl32Version 00258 00259 #---------------------------------------------------------------------------- 00260 00261 class PySimpleApp(wx.App): 00262 """ 00263 A simple application class. You can just create one of these and 00264 then then make your top level windows later, and not have to worry 00265 about OnInit. For example:: 00266 00267 app = wx.PySimpleApp() 00268 frame = wx.Frame(None, title='Hello World') 00269 frame.Show() 00270 app.MainLoop() 00271 00272 :see: `wx.App` 00273 """ 00274 00275 def __init__(self, redirect=False, filename=None, 00276 useBestVisual=False, clearSigInt=True): 00277 """ 00278 :see: `wx.App.__init__` 00279 """ 00280 wx.App.__init__(self, redirect, filename, useBestVisual, clearSigInt) 00281 00282 def OnInit(self): 00283 return True 00284 00285 00286 00287 # Is anybody using this one? 00288 class PyWidgetTester(wx.App): 00289 def __init__(self, size = (250, 100)): 00290 self.size = size 00291 wx.App.__init__(self, 0) 00292 00293 def OnInit(self): 00294 self.frame = wx.Frame(None, -1, "Widget Tester", pos=(0,0), size=self.size) 00295 self.SetTopWindow(self.frame) 00296 return True 00297 00298 def SetWidget(self, widgetClass, *args, **kwargs): 00299 w = widgetClass(self.frame, *args, **kwargs) 00300 self.frame.Show(True) 00301 00302 #---------------------------------------------------------------------------- 00303 # DO NOT hold any other references to this object. This is how we 00304 # know when to cleanup system resources that wxWidgets is holding. When 00305 # the sys module is unloaded, the refcount on sys.__wxPythonCleanup 00306 # goes to zero and it calls the wx.App_CleanUp function. 00307 00308 class __wxPyCleanup: 00309 def __init__(self): 00310 self.cleanup = _core_.App_CleanUp 00311 def __del__(self): 00312 self.cleanup() 00313 00314 _sys.__wxPythonCleanup = __wxPyCleanup() 00315 00316 ## # another possible solution, but it gets called too early... 00317 ## import atexit 00318 ## atexit.register(_core_.wxApp_CleanUp) 00319 00320 00321 #----------------------------------------------------------------------------