Lesson 8: Showing a Dialog
| filename: | lesson08-show_dialog.py |
| getName() | Lesson 08 - Show Dialog |
| getDescription() | Lesson 08 - Show a dialog using the wxPython interface. |
We have learnt a lot about working with your Note Studio data.
Now, it's time to start interracting with a user. We do this via dialog boxes. These allow you to both report information to a user, and collect information from a user.
In this lesson we're going to see some really simple dialogs which report information to the user. In the next lesson we'll
see some more complex ones. We'll jump straight into it. I'll explain more later.
The Message Box
The Message Box is the simplest type of dialog, because it's very easy to use.
The Message Dialog
Let's use one to report our progress in the plugin. We'll tell the user when we enter preExecute().
First, at the top of the file we import the main wxPython module:
from wxPython.wx import *
This imports most of the stuff we need to do GUI programming. Now, down in preExecute, we add this code:
# announce that we're in preExecute() dlg = wxMessageDialog( None, "We're in preExecute()", "Progress Report", wxOK | wxICON_EXCLAMATION ) dlg.ShowModal()
What's going on here? Well, there are two separate operations:
- create the Message Dialog
- show the dialog using ShowModal()
Now, creating the dialog is as simple as passing in four parameters to the wxMessageDialog constructor:
- the parent window (can be None)
- the text you want in the dialog box
- the caption you want to give the dialog box
- some flags which control how the dialog is displayed. The wxOK causes the dialog to have an 'OK' button. The wxICON_EXCLAMATION causes the dialog to have an exclamation mark, or equivalent.
OK, at the moment you have to take my word for all this. But how do you find out what parameters wxMessageDialog() takes,
without me telling you? Well, you need the wxWidgets documentation. I'll tell you more about that in the next lesson. For
now, just take my word for it.
The Parameter List
In this plugin, we're going to give the user a chance to make a choice. We're going to ask the user whether they want to run
the plugin or not. If they answer 'Yes', we're going to make a list of all the books in the library. If they answer 'No',
we're not going to do that. The plugin will just stop running.
By passing different parameters to the wxMessageDialog, we can make it behave differently. Here's how we can ask a Yes/No
question:
#ask a yes-no question shouldRunPlugin = False dlg = wxMessageDialog( None, "Do you really want to run this plugin?", "Are you sure?", wxYES_NO | wxICON_QUESTION ) userChoice = dlg.ShowModal() if userChoice == wxID_YES: shouldRunPlugin = True else: shouldRunPlugin = False
Here we passed wxYES_NO, to give the dialog both a 'Yes' and a 'No' button. Show Modal() shows the dialog. The code pauses
here, while the user is looking at the dialog. When they press either 'Yes' or 'No', the dialog will shut down. Depending
on which button the user presses, this dialog will return either 'wxID_YES' or 'wxID_NO'. We read that return value into a
variable called 'userChoice'. We use this variable to decide whether to run the plugin or not.
Now, here's a trick.
Normally, preExecute returns a list of all the parameters which you collected. If you didn't collect any parameters, just
return an empty list. However, if you return 'None', then this tells Note Studio not to continue running the plugin. Therefore,
we can do this:
if shouldRunPlugin: return [] return None
Now, if the user answers 'Yes', the plugin will be executed.
If the user answers 'No', the plugin will be cancelled. Pretty neat, huh?
A List Box
So what does this plugin actually do? Well, it's going to iterate through all your books, and get their names. It will show
you these names in a list box. The code to iterate through your books is easy - you already have everything you need from
earlier lessons.
The interesting part is the dialog code. You'll see at the top of the plugin is a special dialog class, called 'DlgDisplayBook'. Now, there's a lot to look at here. Firstly, it's a Python class, derived from the base wxDialog.
class DlgDisplayBook(wxDialog):
It has a special __init__ function, where the dialog setup is done:
def __init__( self ): wxDialog.__init__(self, None, -1, "List of Books", wxDefaultPosition, wxSize(352, 200))
We won't explain every single line in the code. But we will list it, so you can get a feel for it. These lines refer to sizers,
which are used to arrange graphics objects within the dialog.
self.SetAutoLayout(true) topSizer = wxBoxSizer( wxVERTICAL ) buttonSizer = wxBoxSizer( wxHORIZONTAL )
Here we create a Static Text item, which works like a label. Then we add a listbox, which will hold the list of book names.
DEFAULT_LB_HEIGHT = 200 txtCtrl = wxStaticText(self, -1, "Here are your books") topSizer.Add( txtCtrl, 0, wxEXPAND | wxEAST | wxWEST, 10 ) topSizer.Add(wxSize( 0, 5) ) self.lb1 = wxListBox(self, -1, wxDefaultPosition,wxSize(350, DEFAULT_LB_HEIGHT), style=wxLB_SINGLE )
We have broken the code which inserts book names into the listbox out to a separate function, below.
self.populateListBox()
Then, at the bottom, we add an OK and a Cancel button.
topSizer.Add( self.lb1, 0, wxEXPAND | wxEAST | wxWEST, 10 ) okButton = wxButton(self, wxID_OK, "OK", wxDefaultPosition, wxDefaultSize) okButton.SetDefault() buttonSizer.Add( okButton, 0, wxEAST|wxWEST,20 ) cancelButton = wxButton(self, wxID_CANCEL, "Cancel", wxDefaultPosition, wxDefaultSize) buttonSizer.Add( cancelButton, 0, wxEAST|wxWEST,20 ) topSizer.Add( wxSize(0, 10) ) topSizer.Add( buttonSizer, 0, wxALIGN_CENTRE ) topSizer.Add( wxSize(0, 5) ) self.SetSizer( topSizer ) topSizer.Fit( self ) self.Layout() self.Centre()
Here is the populateListBox function. You can see it just iterates through the books, and inserts the book names into a list.
def populateListBox( self ): self.lb1.Clear() sampleList = [] for i in range( theAppData.library.getNumBooks() ): book = theAppData.library.getBook(i) sampleList.append( book.getDisplayName() ) self.lb1.InsertItems( sampleList, 0 )
Reporting Success
When the plugin has run successfully, we are going to report success. We do this in postExecute(). By now the code should look familiar:
# announce that we're in preExecute() dlg = wxMessageDialog( None, "We're in postExecute(). Plugin is finished.", "Progress Report", wxOK | wxICON_EXCLAMATION ) dlg.ShowModal()
That's a polite way to end a plugin, especially if it took some time to run.
Conclusion
This has been the first lesson showing you some windowing code. You don't have to understand it all yet. I'll explain in the
next lesson how you can normally cut and paste code to meet your needs.
API Functions:
There were no new Note Studio API functions in this lesson.
The wxPython functions are documented elsewhere. See Plugins - Lesson 09.