source: trunk/doc/src/tutorials/addressbook.qdoc@ 865

Last change on this file since 865 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 42.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:FDL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in a
14** written agreement between you and Nokia.
15**
16** GNU Free Documentation License
17** Alternatively, this file may be used under the terms of the GNU Free
18** Documentation License version 1.3 as published by the Free Software
19** Foundation and appearing in the file included in the packaging of this
20** file.
21**
22** If you have questions regarding the use of this file, please contact
23** Nokia at [email protected].
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \page tutorials-addressbook.html
30
31 \title Address Book Tutorial
32 \brief An introduction to GUI programming, showing how to put together a
33 simple yet fully-functioning application.
34
35 This tutorial is an introduction to GUI programming with the Qt
36 cross-platform framework.
37
38 \image addressbook-tutorial-screenshot.png
39
40 \omit
41 It doesn't cover everything; the emphasis is on teaching the programming
42 philosophy of GUI programming, and Qt's features are introduced as needed.
43 Some commonly used features are never used in this tutorial.
44 \endomit
45
46 In this tutorial, you will learn about some of the basic
47 components of Qt, including:
48
49 \list
50 \o Widgets and layout managers
51 \o Container classes
52 \o Signals and slots
53 \o Input and output devices
54 \endlist
55
56 If you are new to Qt, we recommend reading \l{How to Learn Qt} first.
57
58 Tutorial contents:
59
60 \list 1
61 \o \l{tutorials/addressbook/part1}{Designing the User Interface}
62 \o \l{tutorials/addressbook/part2}{Adding Addresses}
63 \o \l{tutorials/addressbook/part3}{Navigating between Entries}
64 \o \l{tutorials/addressbook/part4}{Editing and Removing Addresses}
65 \o \l{tutorials/addressbook/part5}{Adding a Find Function}
66 \o \l{tutorials/addressbook/part6}{Loading and Saving}
67 \o \l{tutorials/addressbook/part7}{Additional Features}
68 \endlist
69
70 The tutorial source code is located in \c{examples/tutorials/addressbook}.
71
72 Although this little application does not look much like a
73 fully-fledged modern GUI application, it uses many of the basic
74 elements that are used in more complex applications. After you
75 have worked through this tutorial, we recommend reading the
76 \l{mainwindows/application}{Application} example, which presents a
77 small GUI application, with menus, toolbars, a status bar, and so
78 on.
79*/
80
81/*!
82 \page tutorials-addressbook-part1.html
83
84 \example tutorials/addressbook/part1
85 \title Part 1 - Designing the User Interface
86
87 This first part covers the design of the basic graphical user
88 interface (GUI) for our address book application.
89
90 The first step in creating a GUI program is to design the user
91 interface. Here the our goal is to set up the labels and input
92 fields to implement a basic address book. The figure below is a
93 screenshot of the expected output.
94
95 \image addressbook-tutorial-part1-screenshot.png
96
97 We require two QLabel objects, \c nameLabel and \c addressLabel, as well
98 as two input fields, a QLineEdit object, \c nameLine, and a QTextEdit
99 object, \c addressText, to enable the user to enter a contact's name and
100 address. The widgets used and their positions are shown in the figure
101 below.
102
103 \image addressbook-tutorial-part1-labeled-screenshot.png
104
105 There are three files used to implement this address book:
106
107 \list
108 \o \c{addressbook.h} - the definition file for the \c AddressBook
109 class,
110 \o \c{addressbook.cpp} - the implementation file for the
111 \c AddressBook class, and
112 \o \c{main.cpp} - the file containing a \c main() function, with
113 an instance of \c AddressBook.
114 \endlist
115
116 \section1 Qt Programming - Subclassing
117
118 When writing Qt programs, we usually subclass Qt objects to add
119 functionality. This is one of the essential concepts behind creating
120 custom widgets or collections of standard widgets. Subclassing to
121 extend or change the behavior of a widget has the following advantages:
122
123 \list
124 \o We can write implementations of virtual or pure virtual functions to
125 obtain exactly what we need, falling back on the base class's implementation
126 when necessary.
127 \o It allows us to encapsulate parts of the user interface within a class,
128 so that the other parts of the application don't need to know about the
129 individual widgets in the user interface.
130 \o The subclass can be used to create multiple custom widgets in the same
131 application or library, and the code for the subclass can be reused in other
132 projects.
133 \endlist
134
135 Since Qt does not provide a specific address book widget, we subclass a
136 standard Qt widget class and add features to it. The \c AddressBook class
137 we create in this tutorial can be reused in situations where a basic address
138 book widget is needed.
139
140 \section1 Defining the AddressBook Class
141
142 The \l{tutorials/addressbook/part1/addressbook.h}{\c addressbook.h} file is
143 used to define the \c AddressBook class.
144
145 We start by defining \c AddressBook as a QWidget subclass and declaring
146 a constructor. We also use the Q_OBJECT macro to indicate that the class
147 uses internationalization and Qt's signals and slots features, even
148 if we do not use all of these features at this stage.
149
150 \snippet tutorials/addressbook/part1/addressbook.h class definition
151
152 The class holds declarations of \c nameLine and \c addressText,
153 the private instances of QLineEdit and QTextEdit mentioned
154 earlier. The data stored in \c nameLine and \c addressText will
155 be needed for many of the address book functions.
156
157 We don't include declarations of the QLabel objects we will use
158 because we will not need to reference them once they have been
159 created. The way Qt tracks the ownership of objects is explained
160 in the next section.
161
162 The Q_OBJECT macro itself implements some of the more advanced features of Qt.
163 For now, it is useful to think of the Q_OBJECT macro as a shortcut which allows
164 us to use the \l{QObject::}{tr()} and \l{QObject::}{connect()} functions.
165
166 We have now completed the \c addressbook.h file and we move on to
167 implement the corresponding \c addressbook.cpp file.
168
169 \section1 Implementing the AddressBook Class
170
171 The constructor of \c AddressBook accepts a QWidget parameter, \a parent.
172 By convention, we pass this parameter to the base class's constructor.
173 This concept of ownership, where a parent can have one or more children,
174 is useful for grouping widgets in Qt. For example, if you delete a parent,
175 all of its children will be deleted as well.
176
177 \snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields
178
179 In this constructor, the QLabel objects \c nameLabel and \c
180 addressLabel are instantiated, as well as \c nameLine and \c
181 addressText. The \l{QObject::tr()}{tr()} function returns a
182 translated version of the string, if there is one
183 available. Otherwise it returns the string itself. This function
184 marks its QString parameter as one that should be translated into
185 other languages. It should be used wherever a translatable string
186 appears.
187
188 When programming with Qt, it is useful to know how layouts work.
189 Qt provides three main layout classes: QHBoxLayout, QVBoxLayout
190 and QGridLayout to handle the positioning of widgets.
191
192 \image addressbook-tutorial-part1-labeled-layout.png
193
194 We use a QGridLayout to position our labels and input fields in a
195 structured manner. QGridLayout divides the available space into a grid and
196 places widgets in the cells we specify with row and column numbers. The
197 diagram above shows the layout cells and the position of our widgets, and
198 we specify this arrangement using the following code:
199
200 \snippet tutorials/addressbook/part1/addressbook.cpp layout
201
202 Notice that \c addressLabel is positioned using Qt::AlignTop as an
203 additional argument. This is to make sure it is not vertically centered in
204 cell (1,0). For a basic overview on Qt Layouts, refer to the
205 \l{Layout Management} documentation.
206
207 In order to install the layout object onto the widget, we have to invoke
208 the widget's \l{QWidget::setLayout()}{setLayout()} function:
209
210 \snippet tutorials/addressbook/part1/addressbook.cpp setting the layout
211
212 Lastly, we set the widget's title to "Simple Address Book".
213
214 \section1 Running the Application
215
216 A separate file, \c main.cpp, is used for the \c main() function. Within
217 this function, we instantiate a QApplication object, \c app. QApplication
218 is responsible for various application-wide resources, such as the default
219 font and cursor, and for running an event loop. Hence, there is always one
220 QApplication object in every GUI application using Qt.
221
222 \snippet tutorials/addressbook/part1/main.cpp main function
223
224 We construct a new \c AddressBook widget on the stack and invoke
225 its \l{QWidget::show()}{show()} function to display it.
226 However, the widget will not be shown until the application's event loop
227 is started. We start the event loop by calling the application's
228 \l{QApplication::}{exec()} function; the result returned by this function
229 is used as the return value from the \c main() function. At this point,
230 it becomes apparent why we instanciated \c AddressBook on the stack: It
231 will now go out of scope. Therefore, \c AddressBook and all its child widgets
232 will be deleted, thus preventing memory leaks.
233*/
234
235/*!
236 \page tutorials-addressbook-part2.html
237
238 \example tutorials/addressbook/part2
239 \title Part 2 - Adding Addresses
240
241 The next step in creating the address book is to implement some
242 user interactions.
243
244 \image addressbook-tutorial-part2-add-contact.png
245
246 We will provide a push button that the user can click to add a new contact.
247 Also, some form of data structure is needed to store these contacts in an
248 organized way.
249
250 \section1 Defining the AddressBook Class
251
252 Now that we have the labels and input fields set up, we add push buttons to
253 complete the process of adding a contact. This means that our
254 \c addressbook.h file now has three QPushButton objects declared and three
255 corresponding public slots.
256
257 \snippet tutorials/addressbook/part2/addressbook.h slots
258
259 A slot is a function that responds to a particular signal. We will discuss
260 this concept in further detail when implementing the \c AddressBook class.
261 However, for an overview of Qt's signals and slots concept, you can refer
262 to the \l{Signals and Slots} document.
263
264 Three QPushButton objects (\c addButton, \c submitButton, and
265 \c cancelButton) are now included in our private variable declarations,
266 along with \c nameLine and \c addressText.
267
268 \snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration
269
270 We need a container to store our address book contacts, so that we can
271 traverse and display them. A QMap object, \c contacts, is used for this
272 purpose as it holds a key-value pair: the contact's name as the \e key,
273 and the contact's address as the \e{value}.
274
275 \snippet tutorials/addressbook/part2/addressbook.h remaining private variables
276
277 We also declare two private QString objects, \c oldName and \c oldAddress.
278 These objects are needed to hold the name and address of the contact that
279 was last displayed, before the user clicked \gui Add. So, when the user clicks
280 \gui Cancel, we can revert to displaying the details of the last contact.
281
282 \section1 Implementing the AddressBook Class
283
284 Within the constructor of \c AddressBook, we set the \c nameLine and
285 \c addressText to read-only, so that we can only display but not edit
286 existing contact details.
287
288 \dots
289 \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1
290 \dots
291 \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2
292
293 Then, we instantiate our push buttons: \c addButton, \c submitButton, and
294 \c cancelButton.
295
296 \snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration
297
298 The \c addButton is displayed by invoking the \l{QPushButton::show()}
299 {show()} function, while the \c submitButton and \c cancelButton are
300 hidden by invoking \l{QPushButton::hide()}{hide()}. These two push
301 buttons will only be displayed when the user clicks \gui Add and this is
302 handled by the \c addContact() function discussed below.
303
304 \snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots
305
306 We connect the push buttons' \l{QPushButton::clicked()}{clicked()} signal
307 to their respective slots. The figure below illustrates this.
308
309 \image addressbook-tutorial-part2-signals-and-slots.png
310
311 Next, we arrange our push buttons neatly to the right of our address book
312 widget, using a QVBoxLayout to line them up vertically.
313
314 \snippet tutorials/addressbook/part2/addressbook.cpp vertical layout
315
316 The \l{QBoxLayout::addStretch()}{addStretch()} function is used to ensure
317 the push buttons are not evenly spaced, but arranged closer to the top of
318 the widget. The figure below shows the difference between using
319 \l{QBoxLayout::addStretch()}{addStretch()} and not using it.
320
321 \image addressbook-tutorial-part2-stretch-effects.png
322
323 We then add \c buttonLayout1 to \c mainLayout, using
324 \l{QGridLayout::addLayout()}{addLayout()}. This gives us nested layouts
325 as \c buttonLayout1 is now a child of \c mainLayout.
326
327 \snippet tutorials/addressbook/part2/addressbook.cpp grid layout
328
329 Our layout coordinates now look like this:
330
331 \image addressbook-tutorial-part2-labeled-layout.png
332
333 In the \c addContact() function, we store the last displayed contact
334 details in \c oldName and \c oldAddress. Then we clear these input
335 fields and turn off the read-only mode. The focus is set on \c nameLine
336 and we display \c submitButton and \c cancelButton.
337
338 \snippet tutorials/addressbook/part2/addressbook.cpp addContact
339
340 The \c submitContact() function can be divided into three parts:
341
342 \list 1
343 \o We extract the contact's details from \c nameLine and \c addressText
344 and store them in QString objects. We also validate to make sure that the
345 user did not click \gui Submit with empty input fields; otherwise, a
346 QMessageBox is displayed to remind the user for a name and address.
347
348 \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1
349
350 \o We then proceed to check if the contact already exists. If it does not
351 exist, we add the contact to \c contacts and we display a QMessageBox to
352 inform the user that the contact has been added.
353
354 \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2
355
356 If the contact already exists, again, we display a QMessageBox to inform
357 the user about this, preventing the user from adding duplicate contacts.
358 Our \c contacts object is based on key-value pairs of name and address,
359 hence, we want to ensure that \e key is unique.
360
361 \o Once we have handled both cases mentioned above, we restore the push
362 buttons to their normal state with the following code:
363
364 \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3
365
366 \endlist
367
368 The screenshot below shows the QMessageBox object we use to display