Qt in Education
© 2010 Nokia Corporation. All rights reserved.
Lab 2 – Custom Widgets, Graphics View Canvas
Aim: This lab will take you through the steps required to build a Qt
application built around custom widgets and the Graphics View
framework.
Duration: 4 h
© 2010 Nokia Corporation and its Subsidiary(-ies).
The enclosed Qt Materials are provided under the Creative Commons Attribution-Non-Commercial-Share Alike 2.5 License
Agreement.
The full license text is available here: http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode.
Nokia, Qt and the Nokia and Qt logos are the registered trademarks of Nokia Corporation in Finland and other countries
worldwide.
Qt in Education
© 2010 Nokia Corporation. All rights reserved.
Introduction
The goal of this lab is to create an application for creating and solving jigsaw puzzles.
The application that you will create is based on the Graphics View architecture. The scene based
part of the program will be supported by a widget-based dialog built around an application specific
custom widget.
You will have to deal with more complex situations than those from the exercises so take your time
to study each step and consult the reference manual until you are sure you know what you are
doing and why.
In the lab it is assumed that you feel comfortable with using Qt Creator, creating classes and files
in particular. Instructions will focus more on the task at hand than on going into details on how to
perform it.
The whole project consists of two parts. The first one is dedicated to creating a dialog for
configuring a jigsaw puzzle. This involves creating a custom widget for controlling the number of
pieces that will be used.
The second half is about implementing the game itself – the logic, presentation and user
interaction. It involves moving objects on a graphics view canvas. It involves tasks such as custom
items and items that can stick together.
Qt in Education
© 2010 Nokia Corporation. All rights reserved.
The configuration dialog
Start by creating an empty project in Qt Creator. In that project, create a dialog such as the one
shown in the picture below. Choose to base it on the 'Qt Designer Form Class' when adding it to
the project. Name the class ConfigurationDialog.
The large rectangle in the middle of the dialog is a QFrame object with its frameShape property set to
Box. The rest of the dialog is built from labels, a line edit, a dialog button box and an ordinary push
button. Create the dialog and apply the necessary layouts.
After having designed the dialog the first thing that needs to be done is to enable the “Browse”
button. It is intended to show a file dialog for choosing an image that will be the base for the jigsaw
puzzle. Add a custom slot called browseFile() to the code of your dialog and make a signal-slot
connection (by placing an appropriate connect() statement in the constructor of the dialog)
between the button's clicked() signal and your custom slot.
connect(ui->browseButton, SIGNAL(clicked()), SLOT(browseFile()));
Then have the slot use QFileDialog::getOpenFileName() method to ask the user for an image file.
getOpenFileName() accepts a couple of useful parameters. One of them is the file filter string that
limits the list of files the user sees, to those matching the given expression. Have a look into the
documentation to learn about the format of the filter string.
To get a list of image file extensions Qt supports you can call
QImageReader::supportedImageFormats() that will return a list of file extensions. You can
use this list to assemble the filter string. Alternatively just put the common list of
image extensions into the filter.
The return value of the QFileDialog method contains the absolute path to a file chosen by the user
or an empty string if the file choosing dialog was canceled. Set the received file path as text of the
line edit object.
Now create a new C++ implementation file and add the main() function to it. Have it create a
QApplication object and an instance of your dialog. Then call the dialog's exec() method and see if
Qt in Education
© 2010 Nokia Corporation. All rights reserved.
the button works as expected.
To quickly access documentation of a method in Creator hover your mouse pointer
over the name of the method in your code and press the F1 key on the keyboard.
The custom widget
The next step is to implement a custom widget that will be used to control the puzzle’s difficulty
level. The widget will replace the frame instance from your configuration dialog.
Create a new C++ class using QFrame as the base class. Call it PuzzleSizeWidget. Creator will put
some code of the class for you in appropriate files.
Creating a stub
Usually, the first thing to do when implementing a custom widget is to provide all the necessary
functions for the item, get them to compile and give some sort of sane visual output – even if the
behavior and appearance is incorrect. This is called providing a stub for the widget.
In the case of simple widgets, three things need to be implemented: a constructor, a paint event
handler and the sizeHint() method. The first two are added automatically by Qt Creator. The only
thing left for you is to implement the sizeHint() method to define the widget's size to Qt's layout
system. You can return some arbitrary positive size for now. You will be able to correct it later on.
QSize PuzzleSizeWidget::sizeHint() const {
return QSize(300,300);
}
Promoting to a custom widget
Now that you have a stub for the puzzle size widget, you can place the widget in the configuration
dialog instead of the frame that you have put there earlier. To do that, you will “promote” the frame
widget to the custom widget class. You can promote an existing object on any form to a custom
subclass of the widget in question. That is why the custom widget was derived from QFrame.
Open the form in Designer and right click on the frame. Choose “Promote to...” from the context
menu and fill out the necessary data as shown in the image below.
Qt in Education
© 2010 Nokia Corporation. All rights reserved.
In the promotion dialog, click Add and then Promote. The widget has now been promoted.
You will not see any changes in the form while using Designer – the frame is still a QFrame. Qt will
substitute it with the right class during compilation. Build and run the project to see the effect.
If at any time you wish to revert a promotion, you can choose “Demote to QFrame”
from the context menu of the promoted frame object. You can also replace a widget
with an other standard widget – you do that using the “Morph Into” submenu
available in the context menu in Designer.
Designing the API
The widget's job will be to let the user choose the number of pieces in both the horizontal and
vertical direction. For that purpose, a number of properties are need.
The most important property will hold the current number of pieces in either direction. Call it value
and make its type QSize so that a single property can represent both directions. First define the
getter and setter methods and a private class field storing the current value of the property. If the
property value influences the way the widget is painted you should call update() in the setter to
trigger a repaint of the widget.
QSize PuzzleSizeWidget::value() const { return m_size; }
void PuzzleSizeWidget::setValue(const QSize &s) {
if(m_size == s)
return;
m_size = s;
update();
}
It is usually a good practice to emit a signal whenever a property value changes. Declare the