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"):
16 def SetParent(self
, parent
):
17 """Set the window to be used as the popup Frame's parent."""
21 def CreateOutputWindow(self
, st
):
22 self
.frame
= wx
.Frame(self
.parent
, -1, self
.title
,
23 style
=wx
.DEFAULT_FRAME_STYLE | wx
.NO_FULL_REPAINT_ON_RESIZE
)
24 self
.text
= wx
.TextCtrl(self
.frame
, -1, "",
25 style
= wx
.TE_MULTILINE | wx
.TE_READONLY
)
26 self
.text
.AppendText(st
)
27 self
.frame
.SetSize((450, 300))
29 EVT_CLOSE(self
.frame
, self
.OnCloseWindow
)
32 def OnCloseWindow(self
, event
):
33 if self
.frame
is not None:
39 # These methods provide the file-like output behaviour.
40 def write(self
, text
):
42 Create the output window if needed and write the string to it.
43 If not called in the context of the gui thread then uses
44 CallAfter to do the work there.
46 if self
.frame
is None:
47 if not wx
.Thread_IsMain():
48 wx
.CallAfter(self
.CreateOutputWindow
, text
)
50 self
.CreateOutputWindow(text
)
52 if not wx
.Thread_IsMain():
53 wx
.CallAfter(self
.text
.AppendText
, text
)
55 self
.text
.AppendText(text
)
59 if self
.frame
is not None:
60 wx
.CallAfter(self
.frame
.Close
)
64 #----------------------------------------------------------------------
66 _defRedirect
= (wx
.Platform
== '__WXMSW__' or wx
.Platform
== '__WXMAC__')
70 The ``wx.App`` class represents the application and is used to:
72 * bootstrap the wxPython system and initialize the underlying
74 * set and get application-wide properties
75 * implement the windowing system main message or event loop,
76 and to dispatch events to window instances
79 Every application must have a ``wx.App`` instance, and all
80 creation of UI objects should be delayed until after the
81 ``wx.App`` object has been created in order to ensure that the
82 gui platform and wxWidgets have been fully initialized.
84 Normally you would derive from this class and implement an
85 ``OnInit`` method that creates a frame and then calls
86 ``self.SetTopWindow(frame)``.
88 :see: `wx.PySimpleApp` for a simpler app class that can be used directly.
91 outputWindowClass
= PyOnDemandOutputWindow
93 def __init__(self
, redirect
=_defRedirect
, filename
=None, useBestVisual
=False):
95 Construct a ``wx.App`` object.
97 :param redirect: Should ``sys.stdout`` and ``sys.stderr``
98 be redirected? Defaults to True on Windows and Mac,
99 False otherwise. If `filename` is None then output
100 will be redirected to a window that pops up as
101 needed. (You can control what kind of window is
102 created for the output by resetting the class
103 variable ``outputWindowClass`` to a class of your
106 :param filename: The name of a file to redirect output
107 to, if redirect is True.
109 :param useBestVisual: Should the app try to use the best
110 available visual provided by the system (only
111 relevant on systems that have more than one visual.)
112 This parameter must be used instead of calling
113 `SetUseBestVisual` later on because it must be set
114 before the underlying GUI toolkit is initialized.
116 :note: You should override OnInit to do applicaition
117 initialization to ensure that the system, toolkit and
118 wxWidgets are fully initialized.
120 wx
.PyApp
.__init
__(self
)
122 if wx
.Platform
== "__WXMAC__":
125 if not MacOS
.WMAvailable():
127 This program needs access to the screen. Please run with 'pythonw',
128 not 'python', and only when you are logged in on the main display of
134 # This has to be done before OnInit
135 self
.SetUseBestVisual(useBestVisual
)
137 # Set the default handler for SIGINT. This fixes a problem
138 # where if Ctrl-C is pressed in the console that started this
139 # app then it will not appear to do anything, (not even send
140 # KeyboardInterrupt???) but will later segfault on exit. By
141 # setting the default handler then the app will exit, as
142 # expected (depending on platform.)
145 signal
.signal(signal
.SIGINT
, signal
.SIG_DFL
)
149 # Save and redirect the stdio to a window?
151 self
.saveStdio
= (_sys
.stdout
, _sys
.stderr
)
153 self
.RedirectStdio(filename
)
155 # This finishes the initialization of wxWindows and then calls
156 # the OnInit that should be present in the derived class
162 self
.RestoreStdio() # Just in case the MainLoop was overridden
167 def SetTopWindow(self
, frame
):
168 """Set the \"main\" top level window"""
170 self
.stdioWin
.SetParent(frame
)
171 wx
.PyApp
.SetTopWindow(self
, frame
)
175 """Execute the main GUI event loop"""
176 wx
.PyApp
.MainLoop(self
)
180 def RedirectStdio(self
, filename
=None):
181 """Redirect sys.stdout and sys.stderr to a file or a popup window."""
183 _sys
.stdout
= _sys
.stderr
= open(filename
, 'a')
185 self
.stdioWin
= self
.outputWindowClass()
186 _sys
.stdout
= _sys
.stderr
= self
.stdioWin
189 def RestoreStdio(self
):
190 _sys
.stdout
, _sys
.stderr
= self
.saveStdio
194 # change from wx.PyApp_XX to wx.App_XX
195 App_GetMacSupportPCMenuShortcuts
= _core_
.PyApp_GetMacSupportPCMenuShortcuts
196 App_GetMacAboutMenuItemId
= _core_
.PyApp_GetMacAboutMenuItemId
197 App_GetMacPreferencesMenuItemId
= _core_
.PyApp_GetMacPreferencesMenuItemId
198 App_GetMacExitMenuItemId
= _core_
.PyApp_GetMacExitMenuItemId
199 App_GetMacHelpMenuTitleName
= _core_
.PyApp_GetMacHelpMenuTitleName
200 App_SetMacSupportPCMenuShortcuts
= _core_
.PyApp_SetMacSupportPCMenuShortcuts
201 App_SetMacAboutMenuItemId
= _core_
.PyApp_SetMacAboutMenuItemId
202 App_SetMacPreferencesMenuItemId
= _core_
.PyApp_SetMacPreferencesMenuItemId
203 App_SetMacExitMenuItemId
= _core_
.PyApp_SetMacExitMenuItemId
204 App_SetMacHelpMenuTitleName
= _core_
.PyApp_SetMacHelpMenuTitleName
205 App_GetComCtl32Version
= _core_
.PyApp_GetComCtl32Version
207 #----------------------------------------------------------------------------
209 class PySimpleApp(wx
.App
):
211 A simple application class. You can just create one of these and
212 then then make your top level windows later, and not have to worry
213 about OnInit. For example::
215 app = wx.PySimpleApp()
216 frame = wx.Frame(None, title='Hello World')
223 def __init__(self
, redirect
=False, filename
=None, useBestVisual
=False):
225 :see: `wx.App.__init__`
227 wx
.App
.__init
__(self
, redirect
, filename
, useBestVisual
)
230 wx
.InitAllImageHandlers()
235 # Is anybody using this one?
236 class PyWidgetTester(wx
.App
):
237 def __init__(self
, size
= (250, 100)):
239 wx
.App
.__init
__(self
, 0)
242 self
.frame
= wx
.Frame(None, -1, "Widget Tester", pos
=(0,0), size
=self
.size
)
243 self
.SetTopWindow(self
.frame
)
246 def SetWidget(self
, widgetClass
, *args
, **kwargs
):
247 w
= widgetClass(self
.frame
, *args
, **kwargs
)
248 self
.frame
.Show(True)
250 #----------------------------------------------------------------------------
251 # DO NOT hold any other references to this object. This is how we
252 # know when to cleanup system resources that wxWidgets is holding. When
253 # the sys module is unloaded, the refcount on sys.__wxPythonCleanup
254 # goes to zero and it calls the wx.App_CleanUp function.
258 self
.cleanup
= _core_
.App_CleanUp
262 _sys
.__wxPythonCleanup
= __wxPyCleanup()
264 ## # another possible solution, but it gets called too early...
266 ## atexit.register(_core_.wxApp_CleanUp)
269 #----------------------------------------------------------------------------