source: trunk/doc/src/examples/imageviewer.qdoc

Last change on this file 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: 14.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
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 qt-info@nokia.com.
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \example widgets/imageviewer
30 \title Image Viewer Example
31
32 The example shows how to combine QLabel and QScrollArea to
33 display an image. QLabel is typically used for displaying text,
34 but it can also display an image. QScrollArea provides a
35 scrolling view around another widget. If the child widget exceeds
36 the size of the frame, QScrollArea automatically provides scroll
37 bars.
38
39 The example demonstrates how QLabel's ability to scale its
40 contents (QLabel::scaledContents), and QScrollArea's ability to
41 automatically resize its contents (QScrollArea::widgetResizable),
42 can be used to implement zooming and scaling features. In
43 addition the example shows how to use QPainter to print an image.
44
45 \image imageviewer-example.png Screenshot of the Image Viewer example
46
47 With the Image Viewer application, the users can view an image of
48 their choice. The \gui File menu gives the user the possibility
49 to:
50
51 \list
52 \o \gui{Open...} - Open an image file
53 \o \gui{Print...} - Print an image
54 \o \gui{Exit} - Exit the application
55 \endlist
56
57 Once an image is loaded, the \gui View menu allows the users to:
58
59 \list
60 \o \gui{Zoom In} - Scale the image up by 25%
61 \o \gui{Zoom Out} - Scale the image down by 25%
62 \o \gui{Normal Size} - Show the image at its original size
63 \o \gui{Fit to Window} - Stretch the image to occupy the entire window
64 \endlist
65
66 In addition the \gui Help menu provides the users with information
67 about the Image Viewer example in particular, and about Qt in
68 general.
69
70 \section1 ImageViewer Class Definition
71
72 \snippet examples/widgets/imageviewer/imageviewer.h 0
73
74 The \c ImageViewer class inherits from QMainWindow. We reimplement
75 the constructor, and create several private slots to facilitate
76 the menu entries. In addition we create four private functions.
77
78 We use \c createActions() and \c createMenus() when constructing
79 the \c ImageViewer widget. We use the \c updateActions() function
80 to update the menu entries when a new image is loaded, or when
81 the \gui {Fit to Window} option is toggled. The zoom slots use \c
82 scaleImage() to perform the zooming. In turn, \c
83 scaleImage() uses \c adjustScrollBar() to preserve the focal point after
84 scaling an image.
85
86 \section1 ImageViewer Class Implementation
87
88 \snippet examples/widgets/imageviewer/imageviewer.cpp 0
89
90 In the constructor we first create the label and the scroll area.
91
92 We set \c {imageLabel}'s size policy to \l
93 {QSizePolicy::Ignored}{ignored}, making the users able to scale
94 the image to whatever size they want when the \gui {Fit to Window}
95 option is turned on. Otherwise, the default size polizy (\l
96 {QSizePolicy::Preferred}{preferred}) will make scroll bars appear
97 when the scroll area becomes smaller than the label's minimum size
98 hint.
99
100 We ensure that the label will scale its contents to fill all
101 available space, to enable the image to scale properly when
102 zooming. If we omitted to set the \c {imageLabel}'s \l
103 {QLabel::scaledContents}{scaledContents} property, zooming in
104 would enlarge the QLabel, but leave the pixmap at
105 its original size, exposing the QLabel's background.
106
107 We make \c imageLabel the scroll area's child widget, and we make
108 \c scrollArea the central widget of the QMainWindow. At the end
109 we create the associated actions and menus, and customize the \c
110 {ImageViewer}'s appearance.
111
112 \snippet examples/widgets/imageviewer/imageviewer.cpp 1
113 \snippet examples/widgets/imageviewer/imageviewer.cpp 2
114
115 In the \c open() slot, we show a file dialog to the user. The
116 easiest way to create a QFileDialog is to use the static
117 convenience functions. QFileDialog::getOpenFileName() returns an
118 existing file selected by the user. If the user presses \gui
119 Cancel, QFileDialog returns an empty string.
120
121 Unless the file name is a empty string, we check if the file's
122 format is an image format by constructing a QImage which tries to
123 load the image from the file. If the constructor returns a null
124 image, we use a QMessageBox to alert the user.
125
126 The QMessageBox class provides a modal dialog with a short
127 message, an icon, and some buttons. As with QFileDialog the
128 easiest way to create a QMessageBox is to use its static
129 convenience functions. QMessageBox provides a range of different
130 messages arranged along two axes: severity (question,
131 information, warning and critical) and complexity (the number of
132 necessary response buttons). In this particular example an
133 information message with an \gui OK button (the default) is
134 sufficient, since the message is part of a normal operation.
135
136 \snippet examples/widgets/imageviewer/imageviewer.cpp 3
137 \snippet examples/widgets/imageviewer/imageviewer.cpp 4
138
139 If the format is supported, we display the image in \c imageLabel
140 by setting the label's \l {QLabel::pixmap}{pixmap}. Then we enable
141 the \gui Print and \gui {Fit to Window} menu entries and update
142 the rest of the view menu entries. The \gui Open and \gui Exit
143 entries are enabled by default.
144
145 If the \gui {Fit to Window} option is turned off, the
146 QScrollArea::widgetResizable property is \c false and it is
147 our responsibility (not QScrollArea's) to give the QLabel a
148 reasonable size based on its contents. We call
149 \{QWidget::adjustSize()}{adjustSize()} to achieve this, which is
150 essentially the same as
151
152 \snippet doc/src/snippets/code/doc_src_examples_imageviewer.qdoc 0
153
154 In the \c print() slot, we first make sure that an image has been
155 loaded into the application:
156
157 \snippet examples/widgets/imageviewer/imageviewer.cpp 5
158 \snippet examples/widgets/imageviewer/imageviewer.cpp 6
159
160 If the application is built in debug mode, the \c Q_ASSERT() macro
161 will expand to
162
163 \snippet doc/src/snippets/code/doc_src_examples_imageviewer.qdoc 1
164
165 In release mode, the macro simply disappear. The mode can be set
166 in the application's \c .pro file. One way to do so is to add an
167 option to \gui qmake when building the appliction:
168
169 \snippet doc/src/snippets/code/doc_src_examples_imageviewer.qdoc 2
170
171 or
172
173 \snippet doc/src/snippets/code/doc_src_examples_imageviewer.qdoc 3
174
175 Another approach is to add this line directly to the \c .pro
176 file.
177
178 \snippet examples/widgets/imageviewer/imageviewer.cpp 7
179 \snippet examples/widgets/imageviewer/imageviewer.cpp 8
180
181 Then we present a print dialog allowing the user to choose a
182 printer and to set a few options. We construct a painter with a
183 QPrinter as the paint device. We set the painter's window
184 and viewport in such a way that the image is as large as possible
185 on the paper, but without altering its
186 \l{Qt::KeepAspectRatio}{aspect ratio}.
187
188 In the end we draw the pixmap at position (0, 0).
189
190 \snippet examples/widgets/imageviewer/imageviewer.cpp 9
191 \snippet examples/widgets/imageviewer/imageviewer.cpp 10
192
193 We implement the zooming slots using the private \c scaleImage()
194 function. We set the scaling factors to 1.25 and 0.8,
195 respectively. These factor values ensure that a \gui {Zoom In}
196 action and a \gui {Zoom Out} action will cancel each other (since
197 1.25 * 0.8 == 1), and in that way the normal image size can be
198 restored using the zooming features.
199
200 The screenshots below show an image in its normal size, and the
201 same image after zooming in:
202
203 \table
204 \row
205 \o \inlineimage imageviewer-original_size.png
206 \o \inlineimage imageviewer-zoom_in_1.png
207 \o \inlineimage imageviewer-zoom_in_2.png
208 \endtable
209
210 \snippet examples/widgets/imageviewer/imageviewer.cpp 11
211 \snippet examples/widgets/imageviewer/imageviewer.cpp 12
212
213 When zooming, we use the QLabel's ability to scale its contents.
214 Such scaling doesn't change the actual size hint of the contents.
215 And since the \l {QLabel::adjustSize()}{adjustSize()} function
216 use those size hint, the only thing we need to do to restore the
217 normal size of the currently displayed image is to call \c
218 adjustSize() and reset the scale factor to 1.0.
219
220 \snippet examples/widgets/imageviewer/imageviewer.cpp 13
221 \snippet examples/widgets/imageviewer/imageviewer.cpp 14
222
223 The \c fitToWindow() slot is called each time the user toggled
224 the \gui {Fit to Window} option. If the slot is called to turn on
225 the option, we tell the scroll area to resize its child widget
226 with the QScrollArea::setWidgetResizable() function. Then we
227 disable the \gui {Zoom In}, \gui {Zoom Out} and \gui {Normal
228 Size} menu entries using the private \c updateActions() function.
229
230 If the \l {QScrollArea::widgetResizable} property is set to \c
231 false (the default), the scroll area honors the size of its child
232 widget. If this property is set to \c true, the scroll area will
233 automatically resize the widget in order to avoid scroll bars
234 where they can be avoided, or to take advantage of extra space.
235 But the scroll area will honor the minimum size hint of its child
236 widget independent of the widget resizable property. So in this
237 example we set \c {imageLabel}'s size policy to \l
238 {QSizePolicy::Ignored}{ignored} in the constructor, to avoid that
239 scroll bars appear when the scroll area becomes smaller than the
240 label's minimum size hint.
241
242 The screenshots below shows an image in its normal size, and the
243 same image with the \gui {Fit to window} option turned on.
244 Enlarging the window will stretch the image further, as shown in
245 the third screenshot.
246
247 \table
248 \row
249 \o \inlineimage imageviewer-original_size.png
250 \o \inlineimage imageviewer-fit_to_window_1.png
251 \o \inlineimage imageviewer-fit_to_window_2.png
252 \endtable
253
254 If the slot is called to turn off the option, the
255 {QScrollArea::setWidgetResizable} property is set to \c false. We
256 also restore the image pixmap to its normal size by adjusting the
257 label's size to its content. And in the end we update the view
258 menu entries.
259
260 \snippet examples/widgets/imageviewer/imageviewer.cpp 15
261 \snippet examples/widgets/imageviewer/imageviewer.cpp 16
262
263 We implement the \c about() slot to create a message box
264 describing what the example is designed to show.
265
266 \snippet examples/widgets/imageviewer/imageviewer.cpp 17
267 \snippet examples/widgets/imageviewer/imageviewer.cpp 18
268
269 In the private \c createAction() function, we create the
270 actions providing the application features.
271
272 We assign a short-cut key to each action and connect them to the
273 appropiate slots. We only enable the \c openAct and \c exitAxt at
274 the time of creation, the others are updated once an image has
275 been loaded into the application. In addition we make the \c
276 fitToWindowAct \l {QAction::checkable}{checkable}.
277
278 \snippet examples/widgets/imageviewer/imageviewer.cpp 19
279 \snippet examples/widgets/imageviewer/imageviewer.cpp 20
280
281 In the private \c createMenu() function, we add the previously
282 created actions to the \gui File, \gui View and \gui Help menus.
283
284 The QMenu class provides a menu widget for use in menu bars,
285 context menus, and other popup menus. The QMenuBar class provides
286 a horizontal menu bar that consists of a list of pull-down menu
287 items. So at the end we put the menus in the \c {ImageViewer}'s
288 menu bar which we retrieve with the QMainWindow::menuBar()
289 function.
290
291 \snippet examples/widgets/imageviewer/imageviewer.cpp 21
292 \snippet examples/widgets/imageviewer/imageviewer.cpp 22
293
294 The private \c updateActions() function enables or disables the
295 \gui {Zoom In}, \gui {Zoom Out} and \gui {Normal Size} menu
296 entries depending on whether the \gui {Fit to Window} option is
297 turned on or off.
298
299 \snippet examples/widgets/imageviewer/imageviewer.cpp 23
300 \snippet examples/widgets/imageviewer/imageviewer.cpp 24
301
302 In \c scaleImage(), we use the \c factor parameter to calculate
303 the new scaling factor for the displayed image, and resize \c
304 imageLabel. Since we set the
305 \l{QLabel::scaledContents}{scaledContents} property to \c true in
306 the constructor, the call to QWidget::resize() will scale the
307 image displayed in the label. We also adjust the scroll bars to
308 preserve the focal point of the image.
309
310 At the end, if the scale factor is less than 33.3% or greater
311 than 300%, we disable the respective menu entry to prevent the
312 image pixmap from becoming too large, consuming too much
313 resources in the window system.
314
315 \snippet examples/widgets/imageviewer/imageviewer.cpp 25
316 \snippet examples/widgets/imageviewer/imageviewer.cpp 26
317
318 Whenever we zoom in or out, we need to adjust the scroll bars in
319 consequence. It would have been tempting to simply call
320
321 \snippet doc/src/snippets/code/doc_src_examples_imageviewer.qdoc 4
322
323 but this would make the top-left corner the focal point, not the
324 center. Therefore we need to take into account the scroll bar
325 handle's size (the \l{QScrollBar::pageStep}{page step}).
326*/
Note: See TracBrowser for help on using the repository browser.