A modal dialog blocks other widgets from receiving user events until it is closed; in other words, it places the user in dialog mode for the duration of its existence. As you can see from figure 9.1, you can't always distinguish between dialogs and frames by their appearance. In wxPython, the difference between a dialog and a frame is not based on how they display, but is largely a matter of the way in which they handle events.
A dialog is created and deployed somewhat differently from a frame. Listing 9.1 shows the code used to generate figure 9.1. After a dialog is displayed and a button is clicked, the dialog closes, and a message is printed to stdout.
A sample modal dialog
Listing 9.1 Defining a modal dialog import wx class SubclassDialog(wx.Dialog):
<_I Initializing the dialog
None, -1, 'Dialog Subclass'
okButton = wx.Button(self, wx.ID_OK, "OK", pos=(15, 15)) okButton.SetDefault()
cancelButton = wx.Button(self, wx.ID_CANCEL, "Cancel", pos=(115, 15))
if __name__ == '__main__': app = wx.PySimpleApp() dialog = SubclassDialog()
result = dialog.ShowModal() <— Showing the modal dialog if result == wx.ID_OK:
print "OK" else:
print "Cancel" dialog.Destroy()
Compared to the wx.Frame examples in the previous chapter, there are a couple of interesting things to note about this code. In the_init__method, the button is added directly to wx.Dialog, rather than to a wx.Panel. Panels are used much less commonly in dialogs than in frames, partially because dialogs tend to be simpler than frames, but largely because the features of a wx.Panel (standard system background and tab key transversal through the controls) already exist by default in wx.Dialog.
To get the dialog to display modally, use the ShowModal() method. This has a different effect on program execution than the modeless Show() method used for frames. Your application will wait at the point of the ShowModal() call until the dialog is dismissed. The dialog being shown is the only part of the wxPython application that receives user events during that time, although system windows from other applications will still work.
The mode continues until the dialog method EndModal(retCode) is called, which closes the dialog. The retCode argument is an integer value, which is then also returned by the original ShowModal() method. Typically, the application uses the return value to learn how the user closed the dialog as a guide to future processing. However, ending the mode does not destroy or even close the dialog. Keeping the dialog around can be a good thing, because it means that you can store information about the user's selections as data members of the dialog instance, and recover that information from the dialog even after the dialog is closed. In the next sections, we'll see examples of that pattern as we deal with dialogs where the user enters data for use elsewhere in the program.
Since there are no event handlers defined in listing 9.1, you may be wondering how the dialog does anything in response to the button clicks. The behavior is already defined in wx.Dialog. There are two predefined wxPython ID numbers that have special meaning in dialogs. When a wx.Button with the ID wx.id_ok is clicked in a dialog, the mode is ended, the dialog is closed, and wx.id_ok is the return value of the ShowModal() call. Similarly, a button with the ID wx.id_cancel does the same things, but returns the value wx.id_cancel. It's up to the rest of the application to ensure that the semantics of OK and Cancel are appropriately enforced.
Listing 9.1 displays a typical method of dealing with a modal dialog. After the dialog is invoked, the return value is used as the test in an if statement. In this case, we simply print the result. In a more complex example, the wx.id_ok branch would implement the actions that the user took within the dialog, such as opening the file or choosing the color.
Typically you should explicitly destroy a dialog when you are finished with it. This signals the C + + object that it should destroy itself which will then allow the Python parts of it to be garbage collected. If you wish to reuse the dialog later in your application without having to recreate it, perhaps to speed the response time for complex dialogs, you can keep a reference to the dialog and simply call its ShowModal() method when you need to activate it again. Be sure to destroy it when the application is ready to exit, otherwise MainLoop() will see it as a still existing top-level window and will not exit normally.
Was this article helpful?