In this tutorial, we will create an address book application step-by-step using the Qt Visual Studio Add-in. We will also outline how to make a basic project using one of the project wizards and create a form with Qt Designer. In addition, we will also show you how to convert a Visual Studio project file into a qmake compatible .pro file.
Creating a Skeleton Qt Application
The first step is to create a trivial project. To do so, select the New Project dialog in Visual Studio and click the Qt Projects folder. Then select the Qt Application item and type "AddressBook" in theName field.
When you click OK, a project wizard will appear. This wizard has a page listing Qt modules you can link your project against, followed by a page that enables you to specify the name of a skeleton class that will be generated by the wizard as a starting point. For this Address Book example, we will use the default values.
Now, we have a small working Qt application. Press F5 to try it out. The result is an empty window. You can close it by clicking the X button on the title bar.
Designing the Main Dialog
Next, we will design the application's main dialog using Qt Designer. See the Qt Designer Manual for more information.
We begin by adding the widgets and setting their properties. These widgets are then put into layouts. The result is shown below.
Adding the Widgets
We launch Qt Designer by double-clicking on the Form Files\addressbook.ui file in Visual Studio's Solution Explorer.
First, we add the QListWidget. Expand the Item-Based Widgets group in the Widget Box, then click on the List Widget subitem and drag it to the top-left corner of the form. The Property Editor will now display the properties for the QListWidget object. Using this editor, set the ObjectName property to "addressList".
Next, we insert the Add and Delete buttons. Expand the Buttons group in the Widget Box and drag two Push Buttons to the top-right corner of the form. Rename the buttons to "addButton" and "deleteButton", and their Text property to "Add" and "Delete".
Finally, we add two QLabel objects to display the selected item in the list by dragging the Label item from the Display Widgets group onto the form, once for each label.
Rename the first label to "nameLabel" and change its Text property to "<No item selected>"; rename the second label to "emailLabel" and leave its Text property empty.
Try to position the widgets as they appear in the screenshot above.
Adding the Layouts
In order to properly position the widgets and ensure that they resize accordingly when the form is resized, we need to add layouts to the form.
We require a vertical layout for the buttons as well as a spacer to push the buttons to the top of the layout. To add a spacer, drag the Vertical Spacer item from the Spacers group onto the form, located below the push buttons. Then, select the buttons and the spacer (click on each widget while holding Shift) and click Form|Layout Vertically.
The window also needs a layout to manage the positioning of other widgets as well as the button layout. So, we add another layout by selecting the list widget, the two labels and the button layout, and then clicking Form|Layout in a Grid.
Hint: Make sure that the labels are almost as wide as the form; otherwise the grid layout will make them only as wide as the address list.
To preview your form without compiling it, click Form|Preview.... To build and run the application save the form, leave the Qt Designer and press F5 in Visual Studio.
Adding an "Add Address" Dialog
Now that the main dialog is done, we move on to add functionality to our address book application. We would like to have an application that pops up a dialog when the user clicks the Add button. Hence, we require an "Add Address" dialog.
Designing the Dialog
We start by designing the dialog. This time, there is no ready-made .ui file available in the project. So, we select Project|Add Class...|Qt4 Classes|Qt4GuiClass. This will invoke a wizard requesting for a class name. Enter "AddDialog" as the name and "QDialog" as the base class. Then, check the "Multiple Inheritance" checkbox and click on the Finish button.
You will now have an adddialog.ui file in the project's Form Files folder.
To set the properties of the dialog, double-click on adddialog.ui to open the form in Qt Designer. Then, click on the form and set its WindowTitle property to "Add Address". Next, create the following widgets and set their ObjectName and Text properties according to values listed in the table below.
Widget | ObjectName | Text |
---|---|---|
QLabel | "nameText" | "Name:" |
QLabel | "emailText" | "Email:" |
QLineEdit | "nameEdit" | "" |
QLineEdit | "emailEdit" | "" |
QPushButton | "okButton" | "OK" |
Now you can layout your widgets. Hint: Use a grid layout for the labels and line edits.
Connecting to the Dialog's OK Button
We want the OK button to invoke the QDialog::accept() slot, and we do this by clicking on the Edit Signals/Slots toolbar button. You will then enter Qt Designer's Signals and Slots Editing Mode.
Click on the OK button and drag the mouse cursor to an empty area of the form and release the mouse button. The Configure Connection dialog will pop up, allowing you to establish a signal-slot connection between the OK button and the form. Connect the button's clicked() signal to the form's accept() slot.
Displaying the "Add Address" Dialog from the Application
Once we have completed designing the dialog, we have to invoke it when the user clicks the main dialog's Add button. To achieve this behavior, we add a slot to the AddressBook class and invoke theAddDialog from this slot.
Forms created using Qt Designer call QMetaObject::connectSlotsByName() to establish connections between signals emitted by the form's child widgets and slots that follow the naming conventionon_<sender>_<signal>(). To react on clicking the add button you must implement a slot called on_addButton_clicked(). Type in the following lines of code in the slot's body:
AddDialog dialog(this); dialog.exec();
If we want to connect to another signal, instead of clicked(), we have to add another signal to the AddressBook class. This requires editing both the header file (addressbook.h) and the implementation file (addressbook.cpp).
Next, we include adddialog.h to addressbook.cpp:
#include "adddialog.h"
Build and run the program now. If you click on the Add button, the Add Address dialog will pop up. If you click on OK, the dialog will disappear.
Adding Items to the List Widget
When the user clicks OK, we would like to add an item to the QListWidget. To do so, modify the code in the on_addButton_clicked() slot to the following:
AddDialog dialog(this); if (dialog.exec()) { QString name = dialog.nameEdit->text(); QString email = dialog.emailEdit->text(); if (!name.isEmpty() && !email.isEmpty()) { QListWidgetItem *item = new QListWidgetItem(name, ui.addressList); item->setData(Qt::UserRole, email); ui.addressList->setCurrentItem(item); } }
We execute the dialog. If the dialog is accepted, e.g., OK is clicked, we extract the Name an Email fields and create a QListWidgetItem with the given information.
Try out the application. Click Add, enter "John Doe" for the name and "john@johndoe.de" for the email. Click OK. The list widget should now contain the new item.
Displaying the Selected Item
When the user selects an item in the list widget, we would like to update the nameLabel and emailLabel at the bottom of the form. This behavior requires another slot to be added to the AddressBookclass.
In the addressbook.h file, add the following code in the private slots section of the class:
void on_addressList_currentItemChanged();
Then, add the block of code below to addressbook.cpp:
void AddressBook::on_addressList_currentItemChanged() { QListWidgetItem *curItem = ui.addressList->currentItem(); if (curItem) { ui.nameLabel->setText("Name: " + curItem->text()); ui.emailLabel->setText("Email: " + curItem->data(Qt::UserRole).toString()); } else { ui.nameLabel->setText("<No item selected>"); ui.emailLabel->clear(); } }
Thanks to the naming convention, this slot will automatically be connected to addressList's currentItemChanged() signal, and will be invoked whenever the selected item in the list changes.
Adding Functionality for the Delete Button
Similar to the Add button, we implement a slot for the Delete button. Open the addressbook.h file and add a new slot declaration on_deleteButton_clicked(). Then open addressbook.cpp and add the slot definition for on_deleteButton_clicked(). Type the following code in the slot's boy:
QListWidgetItem *curItem = ui.addressList->currentItem(); if (curItem) { int row = ui.addressList->row(curItem); ui.addressList->takeItem(row); delete curItem; if (ui.addressList->count() > 0) ui.addressList->setCurrentRow(0); else on_addressList_currentItemChanged(); }
Your application is now complete!
Creating Qt Project File
If you want to build this application on other platforms, you need to create a .pro file for the project. A simple way to do this is to let the Visual Studio Add-in create a basic .pro file for you by clickingQt|Create Basic .pro File. When the Export Project dialog shows up, ensure that the Create .pri File option is checked, then click OK. Visual Studio will then ask you where to save the .pri file. The default location and name is usually sufficient, so just click Save. For more information about .pro files and their associated .pri files, see Managing Projects.
That's it! You should now have a working .pro file and .pri file for your project. For more complex projects, manually editing the .pro file is required to make it work on all plaforms; however, for our simple project the generated .pro file is sufficient.