1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 | """XRC dialog runner.
This module facilitates creating and running simple dialogs that are defined
in XRC files. The XRC file must define OK and Cancel buttons with XRC IDs of
'ID_OK' and 'ID_CANCEL'. The feature to run a dialog will only set and return
values for controls that support GetValue() and SetValue().
Customizing this to support other types of controls is doable.
The basic principle of operation can be summarized with this sample code:
import wx
from wx import xrc
app = wx.PySimpleApp() # assuming you don't already have an app running
# Load the dialog from the resource file.
res = xrc.XmlResource('dialog.xrc')
dlg = res.LoadDialog(None, 'dlgLogin')
dlg.Fit()
# Configure OK & Cancel buttons for default behavior.
dlg.FindWindowByName('ID_OK' ).SetId(wx.ID_OK)
dlg.FindWindowByName('ID_CANCEL').SetId(wx.ID_CANCEL)
# Run the dialog.
if dlg.ShowModal() == wx.ID_OK:
print 'OK'
else:
print 'Cancel'
# Extract results.
print '%r' % dlg.FindWindowByName('fldUser' ).GetValue()
print '%r' % dlg.FindWindowByName('fldPassword').GetValue()
Once the dialog or frame is created, you are free to use Bind() calls to add
handlers to various controls:
def myHandler(evt):
print 'click!'
dlg.FindWindowByName('myButton').Bind(wx.EVT_BUTTON, myHandler)
"""
import os
import wx
from wx import xrc
resourceCache = dict()
def insureWxApp():
"""Create an instance of PySimpleApp if there is no app already.
This is required by wxPython before creating any GUI objects.
"""
global _wxApp
_wxApp = wx.GetApp()
if not _wxApp:
_wxApp = wx.PySimpleApp()
return _wxApp
def loadXrc(filePath, reload=False):
"""Return an xrc.XmlResource instance."""
filePath = os.path.abspath(filePath)
if reload or (filePath not in resourceCache):
result = xrc.XmlResource(filePath)
resourceCache[filePath] = result
else:
result = resourceCache[filePath]
return result
def escapeSuppressor(evt):
"""wx.EVT_CHAR_HOOK handler that suppresses processing ESC.
By default, if you don't have a Cancel button, wx will trigger the
OK button when you press ESC. Binding this to a dialog will deactivate
the ESC key. We need this when there is no Cancel button.
"""
evt.Skip(evt.GetKeyCode() != wx.WXK_ESCAPE)
def buildDialog(filePath, resourceName, mayCancel, **defaults):
"""Return a configured wx.Dialog.
Assumes that the OK and Cancel buttons are named ID_OK & ID_CANCEL.
"""
res = loadXrc(filePath)
insureWxApp()
dlg = res.LoadDialog(None, resourceName)
assert isinstance(dlg, wx.Dialog)
dlg.Fit()
fetchWidget = dlg.FindWindowByName
bOk = dlg.FindWindowByName('ID_OK')
bCancel = dlg.FindWindowByName('ID_CANCEL')
bOk.SetId(wx.ID_OK)
bCancel.SetId(wx.ID_CANCEL)
if not mayCancel:
bCancel.Disable()
bCancel.Hide()
for name, value in defaults.items():
dlg.FindWindowByName(name).SetValue(value)
if not mayCancel:
dlg.Bind(wx.EVT_CHAR_HOOK, escapeSuppressor)
return dlg
def runDialog(dlg, mayCancel, *itemNames):
"""Run the specified dialog and return the values of the named items.
Return None if the user cancels.
"""
while True:
if dlg.ShowModal() == wx.ID_OK:
result = tuple((dlg.FindWindowByName(name).GetValue()
for name in itemNames))
break
elif mayCancel:
result = None
break
else:
wx.Bell()
return result
def useTemporaryDialog(filePath, resourceName, mayCancel,
*itemNames, **defaults):
"""Create a dialog, run it, capture the results, destroy the dialog,
and return the results.
Return None if the user cancels.
"""
dlg = buildDialog(filePath, resourceName, mayCancel, **defaults)
try:
result = runDialog(dlg, mayCancel, *itemNames)
finally:
dlg.Destroy()
return result
# --- Sample Dialog ---
def askLogin(defaultUser='', defaultPassword='', mayCancel=True):
"""Return None if user cancels; otherwise (user, password) as unicode."""
result = useTemporaryDialog('dialog.xrc', 'dlgLogin', mayCancel,
'fldUser', 'fldPassword',
fldUser=defaultUser,
fldPassword=defaultPassword)
return result
# --- Sample Usage ---
import sys
print askLogin('john_doe', '123', mayCancel=False)
print askLogin()
# --- Sample XRC File named dialog.xrc ---
# Open in XRCed (part of "wxPython Docs Demos & Tools") or wxGlade to edit.
"""
<?xml version="1.0" encoding="utf-8"?>
<resource>
<object class="wxDialog" name="dlgLogin">
<title>Login</title>
<object class="wxBoxSizer">
<orient>wxVERTICAL</orient>
<object class="sizeritem">
<object class="wxFlexGridSizer">
<cols>2</cols>
<rows>2</rows>
<object class="sizeritem">
<object class="wxStaticText">
<label>User:</label>
</object>
<flag>wxALL|wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL</flag>
<border>8</border>
</object>
<object class="sizeritem">
<object class="wxTextCtrl" name="fldUser"/>
<flag>wxALL|wxEXPAND</flag>
<border>8</border>
<minsize>200,20</minsize>
</object>
<object class="sizeritem">
<object class="wxStaticText">
<label>Password:</label>
</object>
<flag>wxALL|wxALIGN_LEFT|wxALIGN_CENTRE_VERTICAL</flag>
<border>8</border>
</object>
<object class="sizeritem">
<object class="wxTextCtrl" name="fldPassword">
<style>wxTE_PASSWORD</style>
</object>
<flag>wxALL|wxEXPAND</flag>
<border>8</border>
</object>
<growablecols>1</growablecols>
</object>
<flag>wxALL|wxEXPAND</flag>
<border>8</border>
</object>
<object class="sizeritem">
<object class="wxBoxSizer">
<orient>wxHORIZONTAL</orient>
<object class="sizeritem">
<object class="wxButton" name="ID_CANCEL">
<label>Cancel</label>
</object>
<flag>wxALL|wxALIGN_BOTTOM</flag>
<border>8</border>
</object>
<object class="sizeritem">
<object class="wxButton" name="ID_OK">
<label>OK</label>
<default>1</default>
</object>
<flag>wxALL|wxALIGN_BOTTOM</flag>
<border>8</border>
</object>
</object>
<option>1</option>
<flag>wxBOTTOM|wxLEFT|wxRIGHT|wxALIGN_RIGHT</flag>
<border>8</border>
</object>
</object>
<centered>1</centered>
<style>wxDEFAULT_DIALOG_STYLE|wxSTAY_ON_TOP|wxRESIZE_BORDER|wxDIALOG_MODAL|wxTAB_TRAVERSAL</style>
</object>
</resource>"""
|