Rapid GUI Programming with Python and Qt. Dialogs By Raed S. Rasheed. Dialogs.
Raed S. Rasheed
Almost every GUI application has at least one dialog, and the majority of GUI applications have one main window with dozens or scores of dialogs. Dialogs can be used to make announcements that are too important to put in the status bar or into a log ﬁle.
In such cases, they typically just have a label for the text and an OK button for the user to press when they’ve read the message. Mostly, dialogs are used to ask users questions. Some are simple and need just a yes or no answer.
One way to classify dialogs is by their “intelligence”, where they may be “dumb”, “standard”, or “smart”, depending on how much knowledge about the application’s data is built into them.
In addition to an intelligence classiﬁcation, dialogs can also be categorized by their modality. An application modal dialog is a dialog that, once invoked, is the only part of an application that the user can interact with. Until the user closes the dialog, they cannot use the rest of the application. The user is, of course, free to interact with other applications, for example, by clicking one to give it the focus.
A window modal dialog is one that works in a similar way to an application modal dialog, except that it only prevents interaction with its parent window, parent’s parent window, and so on up to the top-level parent, as well as the parent windows’ sibling windows.
The opposite of a modal dialog is a modeless dialog. When a modeless dialog is invoked, the user can interact with the dialog, and with the rest of the application.
The Pen Properties dialog
dialog = PenPropertiesDlg(self)
self.width = dialog.widthSpinBox.value()
self.beveled = dialog.beveledCheckBox.isChecked()
self.style = unicode(dialog.styleComboBox.currentText())
def __init__(self, parent=None):
widthLabel = QLabel("&Width:")
self.widthSpinBox = QSpinBox()
self.beveledCheckBox = QCheckBox("&Beveled edges")
self.styleComboBox = QComboBox()
self.styleComboBox.addItems(["Solid", "Dashed", "Dotted",
okButton = QPushButton("&OK")
cancelButton = QPushButton("Cancel")
buttonLayout = QHBoxLayout()
layout = QGridLayout()
layout.addWidget(widthLabel, 0, 0)
layout.addWidget(self.widthSpinBox, 0, 1)
layout.addWidget(self.beveledCheckBox, 0, 2)
layout.addWidget(styleLabel, 1, 0)
layout.addWidget(self.styleComboBox, 1, 1, 1, 2)
layout.addLayout(buttonLayout, 2, 0, 1, 3)
The Pen Properties dialog’s layout
Selected Layout Methods
One key advantage of standard dialogs is that the caller does not need to know about their implementation, only how to set the initial values, and how to get the resultant values if the user clicked OK. Another advantage, at least for modal standard dialogs, is that the user cannot interact with the dialog’s parent windows and their sibling windows, so the relevant parts of the application’s state will probably not change behind the dialog’s back. The main drawback of using a standard dialog is most apparent when it must handle lots of different data items, since all the items must be fed into the dialog and the results retrieved on each invocation, and this may involve many lines of code.
The modal Set Number Format dialog in context
Modal OK/Cancel-Style Dialogs
dialog = numberformatdlg1.NumberFormatDlg(self.format, self)
self.format = dialog.numberFormat()
def __init__(self, format, parent=None):
thousandsLabel = QLabel("&Thousands separator")
self.thousandsEdit = QLineEdit(format["thousandsseparator"])
decimalMarkerLabel = QLabel("Decimal &marker")
self.decimalMarkerEdit = QLineEdit(format["decimalmarker"])
decimalPlacesLabel = QLabel("&Decimal places")
self.redNegativesCheckBox = QCheckBox("&Red negative numbers")
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|
Selected QDialogButtonBox Methods and Signals
The main beneﬁt of using a smart modeless dialog is seen at the point of use. When the dialog is created, it is given references to the calling form’s data structures so that the dialog can update the data structures directly with no further code required at the call point. The downsides are that the dialog must have knowledge of the calling form’s data structures so that it correctly reﬂects the data values into its widgets and only applies changes that are valid, and that, being modeless, there is a risk of the data the dialog depends on being changed from under it if the user interacts with some other part of the application.
Modeless Apply/Close-Style Dialogs
Superﬁcially, the only difference between the modeless and the modal versions of the dialog is the button text. However, there are two other important differences: The calling form’s method creates and invokes the dialog differently, and the dialog must make sure it is deleted, not just hidden, when it is closed. Let us begin by looking at how the dialog is invoked.
dialog = numberformatdlg2.NumberFormatDlg(self.format, self)
self.connect(dialog, SIGNAL("changed"), self.refreshTable)
Modeless “Live” Dialogs
We could create this dialog in exactly the same way as the previous dialog, but we will instead demonstrate a different approach. Rather than creating the dialog when it is needed and then destroying it, creating and destroying on every use, we will create it just once, the ﬁrst time it is needed, and then hide it when the user is ﬁnished with it, showing and hiding on every use.
if self.numberFormatDlg is None:
self.format, self.refreshTable, self)