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
)
68 #----------------------------------------------------------------------
70 _defRedirect
= (wx
.Platform
== '__WXMSW__' or wx
.Platform
== '__WXMAC__')
74 The ``wx.App`` class represents the application and is used to:
76 * bootstrap the wxPython system and initialize the underlying
78 * set and get application-wide properties
79 * implement the windowing system main message or event loop,
80 and to dispatch events to window instances
83 Every application must have a ``wx.App`` instance, and all
84 creation of UI objects should be delayed until after the
85 ``wx.App`` object has been created in order to ensure that the gui
86 platform and wxWidgets have been fully initialized.
88 Normally you would derive from this class and implement an
89 ``OnInit`` method that creates a frame and then calls
90 ``self.SetTopWindow(frame)``.
92 :see: `wx.PySimpleApp` for a simpler app class that can be used
96 outputWindowClass
= PyOnDemandOutputWindow
98 def __init__(self
, redirect
=_defRedirect
, filename
=None,
99 useBestVisual
=False, clearSigInt
=True):
101 Construct a ``wx.App`` object.
103 :param redirect: Should ``sys.stdout`` and ``sys.stderr`` be
104 redirected? Defaults to True on Windows and Mac, False
105 otherwise. If `filename` is None then output will be
106 redirected to a window that pops up as needed. (You can
107 control what kind of window is created for the output by
108 resetting the class variable ``outputWindowClass`` to a
109 class of your choosing.)
111 :param filename: The name of a file to redirect output to, if
114 :param useBestVisual: Should the app try to use the best
115 available visual provided by the system (only relevant on
116 systems that have more than one visual.) This parameter
117 must be used instead of calling `SetUseBestVisual` later
118 on because it must be set before the underlying GUI
119 toolkit is initialized.
121 :param clearSigInt: Should SIGINT be cleared? This allows the
122 app to terminate upon a Ctrl-C in the console like other
125 :note: You should override OnInit to do applicaition
126 initialization to ensure that the system, toolkit and
127 wxWidgets are fully initialized.
129 wx
.PyApp
.__init
__(self
)
131 if wx
.Platform
== "__WXMAC__":
134 if not MacOS
.WMAvailable():
136 This program needs access to the screen. Please run with 'pythonw',
137 not 'python', and only when you are logged in on the main display of
145 # This has to be done before OnInit
146 self
.SetUseBestVisual(useBestVisual
)
148 # Set the default handler for SIGINT. This fixes a problem
149 # where if Ctrl-C is pressed in the console that started this
150 # app then it will not appear to do anything, (not even send
151 # KeyboardInterrupt???) but will later segfault on exit. By
152 # setting the default handler then the app will exit, as
153 # expected (depending on platform.)
157 signal
.signal(signal
.SIGINT
, signal
.SIG_DFL
)
161 # Save and redirect the stdio to a window?
163 self
.saveStdio
= (_sys
.stdout
, _sys
.stderr
)
165 self
.RedirectStdio(filename
)
167 # This finishes the initialization of wxWindows and then calls
168 # the OnInit that should be present in the derived class
174 self
.RestoreStdio() # Just in case the MainLoop was overridden
179 def SetTopWindow(self
, frame
):
180 """Set the \"main\" top level window"""
182 self
.stdioWin
.SetParent(frame
)
183 wx
.PyApp
.SetTopWindow(self
, frame
)
187 """Execute the main GUI event loop"""
188 wx
.PyApp
.MainLoop(self
)
192 def RedirectStdio(self
, filename
=None):
193 """Redirect sys.stdout and sys.stderr to a file or a popup window."""
195 _sys
.stdout
= _sys
.stderr
= open(filename
, 'a')
197 self
.stdioWin
= self
.outputWindowClass()
198 _sys
.stdout
= _sys
.stderr
= self
.stdioWin
201 def RestoreStdio(self
):
202 _sys
.stdout
, _sys
.stderr
= self
.saveStdio
206 # change from wx.PyApp_XX to wx.App_XX
207 App_GetMacSupportPCMenuShortcuts
= _core_
.PyApp_GetMacSupportPCMenuShortcuts
208 App_GetMacAboutMenuItemId
= _core_
.PyApp_GetMacAboutMenuItemId
209 App_GetMacPreferencesMenuItemId
= _core_
.PyApp_GetMacPreferencesMenuItemId
210 App_GetMacExitMenuItemId
= _core_
.PyApp_GetMacExitMenuItemId
211 App_GetMacHelpMenuTitleName
= _core_
.PyApp_GetMacHelpMenuTitleName
212 App_SetMacSupportPCMenuShortcuts
= _core_
.PyApp_SetMacSupportPCMenuShortcuts
213 App_SetMacAboutMenuItemId
= _core_
.PyApp_SetMacAboutMenuItemId
214 App_SetMacPreferencesMenuItemId
= _core_
.PyApp_SetMacPreferencesMenuItemId
215 App_SetMacExitMenuItemId
= _core_
.PyApp_SetMacExitMenuItemId
216 App_SetMacHelpMenuTitleName
= _core_
.PyApp_SetMacHelpMenuTitleName
217 App_GetComCtl32Version
= _core_
.PyApp_GetComCtl32Version
219 #----------------------------------------------------------------------------
221 class PySimpleApp(wx
.App
):
223 A simple application class. You can just create one of these and
224 then then make your top level windows later, and not have to worry
225 about OnInit. For example::
227 app = wx.PySimpleApp()
228 frame = wx.Frame(None, title='Hello World')
235 def __init__(self
, redirect
=False, filename
=None,
236 useBestVisual
=False, clearSigInt
=True):
238 :see: `wx.App.__init__`
240 wx
.App
.__init
__(self
, redirect
, filename
, useBestVisual
, clearSigInt
)
247 # Is anybody using this one?
248 class PyWidgetTester(wx
.App
):
249 def __init__(self
, size
= (250, 100)):
251 wx
.App
.__init
__(self
, 0)
254 self
.frame
= wx
.Frame(None, -1, "Widget Tester", pos
=(0,0), size
=self
.size
)
255 self
.SetTopWindow(self
.frame
)
258 def SetWidget(self
, widgetClass
, *args
, **kwargs
):
259 w
= widgetClass(self
.frame
, *args
, **kwargs
)
260 self
.frame
.Show(True)
262 #----------------------------------------------------------------------------
263 # DO NOT hold any other references to this object. This is how we
264 # know when to cleanup system resources that wxWidgets is holding. When
265 # the sys module is unloaded, the refcount on sys.__wxPythonCleanup
266 # goes to zero and it calls the wx.App_CleanUp function.
270 self
.cleanup
= _core_
.App_CleanUp
274 _sys
.__wxPythonCleanup
= __wxPyCleanup()
276 ## # another possible solution, but it gets called too early...
278 ## atexit.register(_core_.wxApp_CleanUp)
281 #----------------------------------------------------------------------------