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
.DisplayAvailable():
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 # This finishes the initialization of wxWindows and then calls
176 # the OnInit that should be present in the derived class
182 Things that must be done after _BootstrapApp has done its
183 thing, but would be nice if they were already done by the time
184 that OnInit is called.
186 wx
.StockGDI
._initStockObjects
()
189 def __del__(self
, destroy
=wx
.PyApp
.__del
__):
190 self
.RestoreStdio() # Just in case the MainLoop was overridden
194 wx
.PyApp
.Destroy(self
)
197 def SetTopWindow(self
, frame
):
198 """Set the \"main\" top level window"""
200 self
.stdioWin
.SetParent(frame
)
201 wx
.PyApp
.SetTopWindow(self
, frame
)
205 """Execute the main GUI event loop"""
206 wx
.PyApp
.MainLoop(self
)
210 def RedirectStdio(self
, filename
=None):
211 """Redirect sys.stdout and sys.stderr to a file or a popup window."""
213 _sys
.stdout
= _sys
.stderr
= open(filename
, 'a')
215 self
.stdioWin
= self
.outputWindowClass()
216 _sys
.stdout
= _sys
.stderr
= self
.stdioWin
219 def RestoreStdio(self
):
221 _sys
.stdout
, _sys
.stderr
= self
.saveStdio
226 def SetOutputWindowAttributes(self
, title
=None, pos
=None, size
=None):
228 Set the title, position and/or size of the output window if
229 the stdio has been redirected. This should be called before
230 any output would cause the output window to be created.
233 if title
is not None:
234 self
.stdioWin
.title
= title
236 self
.stdioWin
.pos
= pos
238 self
.stdioWin
.size
= size
243 # change from wx.PyApp_XX to wx.App_XX
244 App_GetMacSupportPCMenuShortcuts
= _core_
.PyApp_GetMacSupportPCMenuShortcuts
245 App_GetMacAboutMenuItemId
= _core_
.PyApp_GetMacAboutMenuItemId
246 App_GetMacPreferencesMenuItemId
= _core_
.PyApp_GetMacPreferencesMenuItemId
247 App_GetMacExitMenuItemId
= _core_
.PyApp_GetMacExitMenuItemId
248 App_GetMacHelpMenuTitleName
= _core_
.PyApp_GetMacHelpMenuTitleName
249 App_SetMacSupportPCMenuShortcuts
= _core_
.PyApp_SetMacSupportPCMenuShortcuts
250 App_SetMacAboutMenuItemId
= _core_
.PyApp_SetMacAboutMenuItemId
251 App_SetMacPreferencesMenuItemId
= _core_
.PyApp_SetMacPreferencesMenuItemId
252 App_SetMacExitMenuItemId
= _core_
.PyApp_SetMacExitMenuItemId
253 App_SetMacHelpMenuTitleName
= _core_
.PyApp_SetMacHelpMenuTitleName
254 App_GetComCtl32Version
= _core_
.PyApp_GetComCtl32Version
256 #----------------------------------------------------------------------------
258 class PySimpleApp(wx
.App
):
260 A simple application class. You can just create one of these and
261 then then make your top level windows later, and not have to worry
262 about OnInit. For example::
264 app = wx.PySimpleApp()
265 frame = wx.Frame(None, title='Hello World')
272 def __init__(self
, redirect
=False, filename
=None,
273 useBestVisual
=False, clearSigInt
=True):
275 :see: `wx.App.__init__`
277 wx
.App
.__init
__(self
, redirect
, filename
, useBestVisual
, clearSigInt
)
284 # Is anybody using this one?
285 class PyWidgetTester(wx
.App
):
286 def __init__(self
, size
= (250, 100)):
288 wx
.App
.__init
__(self
, 0)
291 self
.frame
= wx
.Frame(None, -1, "Widget Tester", pos
=(0,0), size
=self
.size
)
292 self
.SetTopWindow(self
.frame
)
295 def SetWidget(self
, widgetClass
, *args
, **kwargs
):
296 w
= widgetClass(self
.frame
, *args
, **kwargs
)
297 self
.frame
.Show(True)
299 #----------------------------------------------------------------------------
300 # DO NOT hold any other references to this object. This is how we
301 # know when to cleanup system resources that wxWidgets is holding. When
302 # the sys module is unloaded, the refcount on sys.__wxPythonCleanup
303 # goes to zero and it calls the wx.App_CleanUp function.
307 self
.cleanup
= _core_
.App_CleanUp
311 _sys
.__wxPythonCleanup
= __wxPyCleanup()
313 ## # another possible solution, but it gets called too early...
315 ## atexit.register(_core_.wxApp_CleanUp)
318 #----------------------------------------------------------------------------