This module allows creating and running a custom dialog box with a single function call. The custom dialog box must first be defined in an external XRC file. Editors like XRCed and wxGlade allow easily designing custom dialog boxes. You can then invoke the dialog box even if your application has no other GUI.
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>"""
|
Creating nice GUI interfaces in wx.Python is much easier by using an XRC editor to create XRC files. This allows prototyping the behavior of the dialog so that it looks good when the user resizes the window. Adding the resulting dialog to your program is simply a matter of loading the resource and then "wiring-up" the controls.
Adding behaviour to the controls generally consists of three phases: set initial data for stateful controls like text boxes, bind behavior to buttons, and extract the results from the relevant controls when the dialog closes.
This particular implementation assumes a dialog with an OK and Cancel button and simple controls. This allows us to get the standard behavior without bothering with event handlers. Extending this for additional buttons or other controls would not be hard.
Note that this application requires installing wxPython. Ideally you should also have an XRC editor such as XRCed (part of "wxPython Docs Demos Creating nice GUI interfaces in wx.Python is much easier by using an XRC editor to create XRC files. This allows prototyping the behavior of the dialog so that it looks good when the user resizes the window. Adding the resulting dialog to your program is simply a matter of loading the resource and then "wiring-up" the controls.
Adding behaviour to the controls generally consists of three phases: set initial data for stateful controls like text boxes, bind behavior to buttons, and extract the results from the relevant controls when the dialog closes.
This particular implementation assumes a dialog with an OK and Cancel button and simple controls. This allows us to get the standard behavior without bothering with event handlers. Extending this for additional buttons or other controls would not be hard.
Note that this application requires installing wxPython. Ideally you should also have an XRC editor such as XRCed (part of "wxPython Docs Demos