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

Last change on this file since 357 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

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