wxSingleChoiceDialog
Instead of using a wxListBox to gather input from a user, you can use the wxSingleChoiceDialog. Upon calling it, a dialog is displayed to the user with a list of items that the user can select. The user may only select one item on the list. At the bottom of the dialog, there is an “OK” button and a “Cancel” button. Let’s create a simple application with the dialog:
from wxPython.wx import *
from wxPython.lib.dialogs import *
application = wxPySimpleApp()
# Create a list of choices
choices = [ ‘Red’, ‘Blue’, ‘Green’, ‘Pink’, ‘White’ ]
# Create the dialog
dialog = wxSingleChoiceDialog ( None, ‘Pick something….’, ‘Dialog Title’, choices )
# Show the dialog
dialog.ShowModal()
# Destroy the dialog
dialog.Destroy()
Of course, to make our dialog of any use, we’ll have to catch the user’s selection and perhaps react to the user pressing the “Cancel” button:
from wxPython.wx import *
application = wxPySimpleApp()
choices = [ ‘Red’, ‘Blue’, ‘Green’, ‘Pink’, ‘White’ ]
dialog = wxSingleChoiceDialog ( None, ‘Pick something….’, ‘Dialog Title’, choices )
# The user pressed the “OK” button in the dialog
if dialog.ShowModal() == wxID_OK:
print ‘Position of selection:’, dialog.GetSelection()
print ‘Selection:’, dialog.GetStringSelection()
# The user exited the dialog without pressing the “OK” button
else:
print ‘You did not select anything.’
dialog.Destroy()
If we want to give the user the option of selecting multiple items by pressing the shift key while clicking a selection or holding down the mouse and moving the cursor down, we can do so with wxMultiChoiceDialog:
from wxPython.wx import *
application = wxPySimpleApp()
choices = [ ‘Red’, ‘Blue’, ‘Green’, ‘Pink’, ‘White’ ]
dialog = wxMultiChoiceDialog ( None, ‘Pick something….’, ‘Dialog Title’, choices )
# The user pressed the “OK” button in the dialog
if dialog.ShowModal() == wxID_OK:
selected = dialog.GetSelections()
for selection in selected:
print str ( selection ) + ‘: ‘ + choices [ selection ]
# The user exited the dialog without pressing the “OK” button
else:
print ‘You did not select anything.’
dialog.Destroy()
{mospagebreak title=wxScrolledMessageDialog}
Suppose you need to display a long message, such as the terms of use for your application. A good way to display this would be to use a wxScrolledMessageDialog. It features a read-only multi-line text box, and it’s very easy to put into your applications:
from wxPython.wx import *
application = wxPySimpleApp()
# Set up the text
text = “””Once upon a time, there lived a knight named Sir Esthimus.
Sir Esthimus decided to marry the princess one day. So, he went to the king
and asked if he could marry his lovely daughter. The king said that he had to
defeat the strongest goblin in the kingdom’s dungeons. The knight agreed to
fight the goblin, and the next day, the king summoned both the beast and the
knight to the town square. A sturdy iron fence had been erected overnight to
keep the two fighters inside. The king waved his hand — the signal for the match
to begin. The knight pulled out his sword, and goblin pulled out his spear. The goblin
then pierced the knight’s sword arm, so the knight lost the fight and did not get to marry
the princess.
Notice the scrollbar to the right. It enables you to
write
large
amounts
of
text
to
the
dialog and have it organized neatly.”””
# Create the dialog
dialog = wxScrolledMessageDialog ( self, text, ‘Fairy Tale’ )
# Show the dialog
dialog.ShowModal()
{mospagebreak title=wxProgressDialog}
Any time you are required to do large amounts of work in your application, it is a good idea to let the user know your application’s progress in the process. A wxProgressDialog will do the job nicely. Let’s emulate an application that takes a long time:
import time
for x in xrange ( 25 ):
# Spend some time doing nothing
time.sleep ( 2 )
When running it, I have no idea how much progress has been made. This is easily fixed. Let’s make a wxProgressDialog and update it after each cycle in the loop:
from wxPython.wx import *
application = wxPySimpleApp()
# Create a dialog to show progress
dialog = wxProgressDialog ( ‘Progress’, ‘Doing nothing in a large amount of time.’, maximum = 25 )
for x in xrange ( 25 ):
# Spend some time doing nothing
# We’ll use wxSleep rather than time.sleep
wxSleep ( 2 )
# Update our progress and change the message
dialog.Update ( x + 1, ‘On step ‘ + str ( x + 1 ) + ‘.’ )
Our dialog makes things a lot better. I’m sure you’re wondering what the maximum argument is for. Basically, it sets the maximum number that can be set in Update. Once that maximum is hit, the dialog’s progress bar will be complete. It’s very simple. Because we call the sleep method 25 times, I made maximum match that. You can set maximum to whatever you wish. The default is 100.
Notice that as soon as our task is complete, the dialog is hidden from us. This is because of the wxPD_AUTO_HIDE style, which is applied by default. It hides the dialog once maximum is reached. We can change this by manually setting the style:
from wxPython.wx import *
application = wxPySimpleApp()
dialog = wxProgressDialog ( ‘Progress’, ‘Doing nothing in a large amount of time.’, maximum = 25, style = wxPD_APP_MODAL )
for x in xrange ( 25 ):
wxSleep ( 2 )
dialog.Update ( x + 1, ‘On step ‘ + str ( x + 1 ) + ‘.’ )
If we want to improve our progress dialog even more, we can do so by applying the wxPD_ELAPSED_TIME style, which shows the total amount of time that has gone by since the start of the process:
from wxPython.wx import *
application = wxPySimpleApp()
dialog = wxProgressDialog ( ‘Progress’, ‘Doing nothing in a large amount of time.’, maximum = 5, style = wxPD_APP_MODAL | wxPD_ELAPSED_TIME)
for x in xrange ( 5 ):
wxSleep ( 2 )
dialog.Update ( x + 1, ‘On step ‘ + str ( x + 1 ) + ‘.’ )
To accompany the wxPD_ELAPSED_TIME style, we can apply the wxPD_ESTIMATED_TIME style. It shows the total time that wxPython thinks the process will take:
from wxPython.wx import *
application = wxPySimpleApp()
dialog = wxProgressDialog ( ‘Progress’, ‘Doing nothing in a large amount of time.’, maximum = 5, style = wxPD_APP_MODAL | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME )
for x in xrange ( 5 ):
wxSleep ( 2 )
dialog.Update ( x + 1, ‘On step ‘ + str ( x + 1 ) + ‘.’ )
Alternatively, we can pass wxPD_REMAINING_TIME. It displays the time wxPython believes is left until the process is finished:
from wxPython.wx import *
application = wxPySimpleApp()
dialog = wxProgressDialog ( ‘Progress’, ‘Doing nothing in a large amount of time.’, maximum = 5, style = wxPD_APP_MODAL | wxPD_ELAPSED_TIME | wxPD_REMAINING_TIME )
for x in xrange ( 5 ):
wxSleep ( 2 )
dialog.Update ( x + 1, ‘On step ‘ + str ( x + 1 ) + ‘.’ )
{mospagebreak title=ImageDialog}
The ImageDialog is a very nice dialog. It displays the images in a given directory. It’s very simple to use:
from wxPython.wx import *
# Import the required module
from wxPython.lib import imagebrowser
application = wxPySimpleApp()
# Create the dialog
dialog = imagebrowser.ImageDialog ( None )
# Show the dialog
dialog.ShowModal()
# Destroy the dialog
dialog.Destroy()
Of course, we’ll need to retrieve the file name of the image that the user specifies. This is easily done:
from wxPython.wx import *
from wxPython.lib import imagebrowser
application = wxPySimpleApp()
dialog = imagebrowser.ImageDialog ( None )
# Display the file name if the user selected one
if dialog.ShowModal() == wxID_OK:
print ‘You picked:’, dialog.GetFile()
# Otherwise, yell and scream at the user for cancelling
else:
print ‘You did not select an image!’
dialog.Destroy()
If we need to set a directory other than the current directory, it’s possible to do so by passing a second argument:
from wxPython.wx import *
from wxPython.lib import imagebrowser
application = wxPySimpleApp()
# Specify a directory
dialog = imagebrowser.ImageDialog ( None, ‘C:’ )
if dialog.ShowModal() == wxID_OK:
print ‘You picked:’, dialog.GetFile()
else:
print ‘You did not select an image!’
dialog.Destroy()
{mospagebreak title=wxDirDialog}
If your application requires the user to select a directory for something, consider using wxDirDialog. It allows the user to pick a directory from a tree:
from wxPython.wx import *
application = wxPySimpleApp()
# Create the dialog
dialog = wxDirDialog ( None, message = ‘Pick a directory.’ )
# Show the dialog and get user input
if dialog.ShowModal() == wxID_OK:
print ‘Directory:’, dialog.GetPath()
# The user cancelled
else:
print ‘No directory.’
# Get rid of the dialog
dialog.Destroy()
It is also possible to allow the user to create a new directory from within the dialog by passing the wxDD_NEW_DIR_BUTTON style:
from wxPython.wx import *
application = wxPySimpleApp()
dialog = wxDirDialog ( None, message = ‘Pick a directory.’, style = wxDD_NEW_DIR_BUTTON )
if dialog.ShowModal() == wxID_OK:
print ‘Directory:’, dialog.GetPath()
else:
print ‘No directory.’
dialog.Destroy()
{mospagebreak title=wxFileDialog}
The last dialog we are going to examine in this article is the wxFileDialog. It allows the user to save or open a file. Setting up a basic dialog is pretty simple. Let’s set up one that allows the user to select a file to open:
from wxPython.wx import *
application = wxPySimpleApp()
# Create an open file dialog
dialog = wxFileDialog ( None, style = wxOPEN )
# Show the dialog and get user input
if dialog.ShowModal() == wxID_OK:
print ‘Selected:’, dialog.GetPath()
# The user did not select anything
else:
print ‘Nothing was selected.’
# Destroy the dialog
dialog.Destroy()
Let’s make our dialog more complicated. First, let’s create some filters so the user can select a file type from a list. Second, let’s display a message on the dialog. Third, let’s allow multiple files to be selected:
from wxPython.wx import *
application = wxPySimpleApp()
# Create a list of filters
# This should be fairly simple to follow, so no explanation is necessary
filters = ‘All files (*.*)|*.*|Text files (*.txt)|*.txt’
dialog = wxFileDialog ( None, message = ‘Open something….’, wildcard = filters, style = wxOPEN | wxMULTIPLE )
if dialog.ShowModal() == wxID_OK:
# We’ll have to make room for multiple files here
selected = dialog.GetPaths()
for selection in selected:
print ‘Selected:’, selection
else:
print ‘Nothing was selected.’
dialog.Destroy()
Now let’s create a dialog that allows us to save files. This is done by simply changing the style wxOPEN to wxSAVE:
from wxPython.wx import *
application = wxPySimpleApp()
# Create a save file dialog
dialog = wxFileDialog ( None, style = wxSAVE )
# Show the dialog and get user input
if dialog.ShowModal() == wxID_OK:
print ‘Selected:’, dialog.GetPath()
# The user did not select anything
else:
print ‘Nothing was selected.’
# Destroy the dialog
dialog.Destroy()
A lot of applications present the user with a confirmation dialog if he or she selects a file that already exists. This can be accomplished in your own application by using wxOVERWRITE_PROMPT:
from wxPython.wx import *
application = wxPySimpleApp()
# Create a save file dialog
dialog = wxFileDialog ( None, style = wxSAVE | wxOVERWRITE_PROMPT )
# Show the dialog and get user input
if dialog.ShowModal() == wxID_OK:
print ‘Selected:’, dialog.GetPath()
# The user did not select anything
else:
print ‘Nothing was selected.’
# Destroy the dialog
dialog.Destroy()
Conclusion
We’ve looked at a variety of dialogs that wxPython provides. Dialogs allow programmers to implement common features in their applications without doing much work at all. Instead of working with complex controls to do a simple task, a programmer can call a few methods and have it all done for him or her. All dialogs are simple to create and manage, as this article has thrown through examples. They are worth using in many wxPython applications – both large and small.