- Getting Qt
- Writing Dialogs in Code
- Visual Dialog Design with Qt Designer
- Conclusion
Visual Dialog Design with Qt Designer
Qt Designer is a visual user-interface design tool (see Figure 4). Although Qt makes it relatively easy to write dialogs purely as code, there are many good reasons to use Qt Designer instead:
It generally takes less time to develop a dialog using Qt Designer than to develop the same form in pure code.
Qt Designer makes it easy to experiment with various layouts very quickly, without requiring you to write any code or compile anything.
If you work in a company where the user interface design is done by a team of designers, the designers can use Qt Designer to create the forms directly, instead of producing specifications that the developers then need to implement.
To see how Qt Designer works, let's use it to redo the Find dialog.
Figure 4 Qt Designer in action.
Creating a dialog in Qt Designer typically involves the following steps:
Put the required child widgets on the form, positioned roughly where they belong (see Figure 5).
Set up their propertiesvariable name, text, state, etc. (see Figure 6).
Group the widgets by using layouts.
Specify the tab order.
The first step, putting the required child widgets on the form, is accomplished by clicking the desired widget from the toolbox on the left side of Qt Designer's main window, followed by clicking the desired position on the form. For the moment, we don't need to worry too much about the precise position and size of the child widgets; soon enough we'll put them into layouts, which will take care of those aspects automatically.
Figure 5 The dialog with some widgets.
Figure 6 The dialog with properties set.
Next, we set the child widgets' properties by using the property editor, located on the right side of Qt Designer's main window. The following table summarizes the properties to set for each widget:
Widget |
Property |
Value |
Form1 |
name |
"FindDialogBase" |
caption |
"Find" |
|
lineEdit1 |
name |
"lineEdit" |
textLabel1 |
name |
"label" |
text |
"Find &what:" |
|
buddy |
"lineEdit" |
|
buttonGroup1 |
name |
"buttonGroup" |
title |
"&Direction" | |
radioButton1 |
name |
"upRadioButton" |
text |
"&Up" | |
radioButton2 |
name |
"downRadioButton" |
text |
"&Down" | |
checkBox1 |
checked |
True |
name |
"caseCheckBox" | |
text |
"&Case sensitive" | |
pushButton1 |
name |
"findNextButton" |
text |
"&Find Next" | |
default |
True | |
pushButton2 |
name |
"closeButton" |
text |
"Close" |
After the properties are set, the dialog should look like the one shown earlier in Figure 6.
The next step is to put the widgets inside layouts. You simply select one or more widgets and then choose the appropriate layout from the Layout menu: Lay Out Horizontally, Lay Out Vertically, or Lay Out in a Grid. We'll start with the Find what label:
Click the form to deselect any selected widgets.
Shift-click the widgets you want to lay out. For this example, that's the label and the line edit.
Open the Layout menu and click Lay Out Horizontally.
Select the horizontal layout we've just created, the button group, and the Case Sensitive check box, and put them in a vertical layout.
-
Repeat the same process for the Find Next and Close buttons.
Click the form itself; then choose Layout, Lay Out Horizontally to create the outer layout.
One subtle issue remains: In the code version of the dialog, we could simply call setColumns(2) on the QButtonGroup to make it automatically lay out its children. In Qt Designer, this is achieved by clicking the button group and choosing Lay Out Horizontally from the Layout menu.
When everything else is done, we're ready to set the dialog's tab order. Press F4, click the widgets in the order you want them to have in the tab chain, and press Esc to terminate. Qt Designer displays the tab order as numbers in blue circles, as shown in Figure 8.
Finally, save the dialog as a .ui file, which contains the dialog in an XML format that Qt Designer can load and save.
As Figure 7 shows, the resulting layout is displayed as a red frame in Qt Designer, to make it tangible. (The red frame doesn't appear in the running dialog.)
Figure 7 The dialog with layouts.
Figure 8 Setting the dialog's tab order.
This file is converted to C++ using a separate tool called uic (User Interface Compiler). Assuming that the .ui file is called finddialogbase.ui, the resulting C++ code would appear in the finddialogbase.h and finddialogbase.cpp files.
The dialog looks identical to the one we developed earlier purely in code, but right now if the user presses Find Next or Close, nothing happens! This is solved by subclassing the uic-generated class and adding the missing functionality there, as follows.
Header file:
#ifndef FINDDIALOG_H #define FINDDIALOG_H #include "finddialogbase.h" class FindDialog : public FindDialogBase { Q_OBJECT public: FindDialog(QWidget *parent = 0); signals: void findNext(const QString &text, bool caseSensitive, bool forward); private slots: void findNextButtonClicked(); }; #endif
Implementation file:
#include <qcheckbox.h> #include <qlayout.h> #include <qlineedit.h> #include <qpushbutton.h> #include <qradiobutton.h> #include "finddialog.h" FindDialog::FindDialog(QWidget *parent) : FindDialogBase(parent) { connect(findNextButton, SIGNAL(clicked()), this, SLOT(findNextButtonClicked())); connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); } void FindDialog::findNextButtonClicked() { emit findNext(lineEdit->text(), caseCheckBox->isOn(), upRadioButton->isOn()); }