summaryrefslogtreecommitdiffstats
path: root/doc/src/examples/imageviewer.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/examples/imageviewer.qdoc')
-rw-r--r--doc/src/examples/imageviewer.qdoc326
1 files changed, 326 insertions, 0 deletions
diff --git a/doc/src/examples/imageviewer.qdoc b/doc/src/examples/imageviewer.qdoc
new file mode 100644
index 0000000000..f1d02c3abc
--- /dev/null
+++ b/doc/src/examples/imageviewer.qdoc
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example widgets/imageviewer
+ \title Image Viewer Example
+
+ The example shows how to combine QLabel and QScrollArea to
+ display an image. QLabel is typically used for displaying text,
+ but it can also display an image. QScrollArea provides a
+ scrolling view around another widget. If the child widget exceeds
+ the size of the frame, QScrollArea automatically provides scroll
+ bars.
+
+ The example demonstrates how QLabel's ability to scale its
+ contents (QLabel::scaledContents), and QScrollArea's ability to
+ automatically resize its contents (QScrollArea::widgetResizable),
+ can be used to implement zooming and scaling features. In
+ addition the example shows how to use QPainter to print an image.
+
+ \image imageviewer-example.png Screenshot of the Image Viewer example
+
+ With the Image Viewer application, the users can view an image of
+ their choice. The \gui File menu gives the user the possibility
+ to:
+
+ \list
+ \o \gui{Open...} - Open an image file
+ \o \gui{Print...} - Print an image
+ \o \gui{Exit} - Exit the application
+ \endlist
+
+ Once an image is loaded, the \gui View menu allows the users to:
+
+ \list
+ \o \gui{Zoom In} - Scale the image up by 25%
+ \o \gui{Zoom Out} - Scale the image down by 25%
+ \o \gui{Normal Size} - Show the image at its original size
+ \o \gui{Fit to Window} - Stretch the image to occupy the entire window
+ \endlist
+
+ In addition the \gui Help menu provides the users with information
+ about the Image Viewer example in particular, and about Qt in
+ general.
+
+ \section1 ImageViewer Class Definition
+
+ \snippet examples/widgets/imageviewer/imageviewer.h 0
+
+ The \c ImageViewer class inherits from QMainWindow. We reimplement
+ the constructor, and create several private slots to facilitate
+ the menu entries. In addition we create four private functions.
+
+ We use \c createActions() and \c createMenus() when constructing
+ the \c ImageViewer widget. We use the \c updateActions() function
+ to update the menu entries when a new image is loaded, or when
+ the \gui {Fit to Window} option is toggled. The zoom slots use \c
+ scaleImage() to perform the zooming. In turn, \c
+ scaleImage() uses \c adjustScrollBar() to preserve the focal point after
+ scaling an image.
+
+ \section1 ImageViewer Class Implementation
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 0
+
+ In the constructor we first create the label and the scroll area.
+
+ We set \c {imageLabel}'s size policy to \l
+ {QSizePolicy::Ignored}{ignored}, making the users able to scale
+ the image to whatever size they want when the \gui {Fit to Window}
+ option is turned on. Otherwise, the default size polizy (\l
+ {QSizePolicy::Preferred}{preferred}) will make scroll bars appear
+ when the scroll area becomes smaller than the label's minimum size
+ hint.
+
+ We ensure that the label will scale its contents to fill all
+ available space, to enable the image to scale properly when
+ zooming. If we omitted to set the \c {imageLabel}'s \l
+ {QLabel::scaledContents}{scaledContents} property, zooming in
+ would enlarge the QLabel, but leave the pixmap at
+ its original size, exposing the QLabel's background.
+
+ We make \c imageLabel the scroll area's child widget, and we make
+ \c scrollArea the central widget of the QMainWindow. At the end
+ we create the associated actions and menus, and customize the \c
+ {ImageViewer}'s appearance.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 1
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 2
+
+ In the \c open() slot, we show a file dialog to the user. The
+ easiest way to create a QFileDialog is to use the static
+ convenience functions. QFileDialog::getOpenFileName() returns an
+ existing file selected by the user. If the user presses \gui
+ Cancel, QFileDialog returns an empty string.
+
+ Unless the file name is a empty string, we check if the file's
+ format is an image format by constructing a QImage which tries to
+ load the image from the file. If the constructor returns a null
+ image, we use a QMessageBox to alert the user.
+
+ The QMessageBox class provides a modal dialog with a short
+ message, an icon, and some buttons. As with QFileDialog the
+ easiest way to create a QMessageBox is to use its static
+ convenience functions. QMessageBox provides a range of different
+ messages arranged along two axes: severity (question,
+ information, warning and critical) and complexity (the number of
+ necessary response buttons). In this particular example an
+ information message with an \gui OK button (the default) is
+ sufficient, since the message is part of a normal operation.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 3
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 4
+
+ If the format is supported, we display the image in \c imageLabel
+ by setting the label's \l {QLabel::pixmap}{pixmap}. Then we enable
+ the \gui Print and \gui {Fit to Window} menu entries and update
+ the rest of the view menu entries. The \gui Open and \gui Exit
+ entries are enabled by default.
+
+ If the \gui {Fit to Window} option is turned off, the
+ QScrollArea::widgetResizable property is \c false and it is
+ our responsibility (not QScrollArea's) to give the QLabel a
+ reasonable size based on its contents. We call
+ \{QWidget::adjustSize()}{adjustSize()} to achieve this, which is
+ essentially the same as
+
+ \snippet doc/src/snippets/code/doc_src_examples_imageviewer.cpp 0
+
+ In the \c print() slot, we first make sure that an image has been
+ loaded into the application:
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 5
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 6
+
+ If the application is built in debug mode, the \c Q_ASSERT() macro
+ will expand to
+
+ \snippet doc/src/snippets/code/doc_src_examples_imageviewer.cpp 1
+
+ In release mode, the macro simply disappear. The mode can be set
+ in the application's \c .pro file. One way to do so is to add an
+ option to \gui qmake when building the appliction:
+
+ \snippet doc/src/snippets/code/doc_src_examples_imageviewer.qdoc 2
+
+ or
+
+ \snippet doc/src/snippets/code/doc_src_examples_imageviewer.qdoc 3
+
+ Another approach is to add this line directly to the \c .pro
+ file.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 7
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 8
+
+ Then we present a print dialog allowing the user to choose a
+ printer and to set a few options. We construct a painter with a
+ QPrinter as the paint device. We set the painter's window
+ and viewport in such a way that the image is as large as possible
+ on the paper, but without altering its
+ \l{Qt::KeepAspectRatio}{aspect ratio}.
+
+ In the end we draw the pixmap at position (0, 0).
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 9
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 10
+
+ We implement the zooming slots using the private \c scaleImage()
+ function. We set the scaling factors to 1.25 and 0.8,
+ respectively. These factor values ensure that a \gui {Zoom In}
+ action and a \gui {Zoom Out} action will cancel each other (since
+ 1.25 * 0.8 == 1), and in that way the normal image size can be
+ restored using the zooming features.
+
+ The screenshots below show an image in its normal size, and the
+ same image after zooming in:
+
+ \table
+ \row
+ \o \inlineimage imageviewer-original_size.png
+ \o \inlineimage imageviewer-zoom_in_1.png
+ \o \inlineimage imageviewer-zoom_in_2.png
+ \endtable
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 11
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 12
+
+ When zooming, we use the QLabel's ability to scale its contents.
+ Such scaling doesn't change the actual size hint of the contents.
+ And since the \l {QLabel::adjustSize()}{adjustSize()} function
+ use those size hint, the only thing we need to do to restore the
+ normal size of the currently displayed image is to call \c
+ adjustSize() and reset the scale factor to 1.0.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 13
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 14
+
+ The \c fitToWindow() slot is called each time the user toggled
+ the \gui {Fit to Window} option. If the slot is called to turn on
+ the option, we tell the scroll area to resize its child widget
+ with the QScrollArea::setWidgetResizable() function. Then we
+ disable the \gui {Zoom In}, \gui {Zoom Out} and \gui {Normal
+ Size} menu entries using the private \c updateActions() function.
+
+ If the \l {QScrollArea::widgetResizable} property is set to \c
+ false (the default), the scroll area honors the size of its child
+ widget. If this property is set to \c true, the scroll area will
+ automatically resize the widget in order to avoid scroll bars
+ where they can be avoided, or to take advantage of extra space.
+ But the scroll area will honor the minimum size hint of its child
+ widget independent of the widget resizable property. So in this
+ example we set \c {imageLabel}'s size policy to \l
+ {QSizePolicy::Ignored}{ignored} in the constructor, to avoid that
+ scroll bars appear when the scroll area becomes smaller than the
+ label's minimum size hint.
+
+ The screenshots below shows an image in its normal size, and the
+ same image with the \gui {Fit to window} option turned on.
+ Enlarging the window will stretch the image further, as shown in
+ the third screenshot.
+
+ \table
+ \row
+ \o \inlineimage imageviewer-original_size.png
+ \o \inlineimage imageviewer-fit_to_window_1.png
+ \o \inlineimage imageviewer-fit_to_window_2.png
+ \endtable
+
+ If the slot is called to turn off the option, the
+ {QScrollArea::setWidgetResizable} property is set to \c false. We
+ also restore the image pixmap to its normal size by adjusting the
+ label's size to its content. And in the end we update the view
+ menu entries.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 15
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 16
+
+ We implement the \c about() slot to create a message box
+ describing what the example is designed to show.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 17
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 18
+
+ In the private \c createAction() function, we create the
+ actions providing the application features.
+
+ We assign a short-cut key to each action and connect them to the
+ appropiate slots. We only enable the \c openAct and \c exitAxt at
+ the time of creation, the others are updated once an image has
+ been loaded into the application. In addition we make the \c
+ fitToWindowAct \l {QAction::checkable}{checkable}.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 19
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 20
+
+ In the private \c createMenu() function, we add the previously
+ created actions to the \gui File, \gui View and \gui Help menus.
+
+ The QMenu class provides a menu widget for use in menu bars,
+ context menus, and other popup menus. The QMenuBar class provides
+ a horizontal menu bar that consists of a list of pull-down menu
+ items. So at the end we put the menus in the \c {ImageViewer}'s
+ menu bar which we retrieve with the QMainWindow::menuBar()
+ function.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 21
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 22
+
+ The private \c updateActions() function enables or disables the
+ \gui {Zoom In}, \gui {Zoom Out} and \gui {Normal Size} menu
+ entries depending on whether the \gui {Fit to Window} option is
+ turned on or off.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 23
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 24
+
+ In \c scaleImage(), we use the \c factor parameter to calculate
+ the new scaling factor for the displayed image, and resize \c
+ imageLabel. Since we set the
+ \l{QLabel::scaledContents}{scaledContents} property to \c true in
+ the constructor, the call to QWidget::resize() will scale the
+ image displayed in the label. We also adjust the scroll bars to
+ preserve the focal point of the image.
+
+ At the end, if the scale factor is less than 33.3% or greater
+ than 300%, we disable the respective menu entry to prevent the
+ image pixmap from becoming too large, consuming too much
+ resources in the window system.
+
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 25
+ \snippet examples/widgets/imageviewer/imageviewer.cpp 26
+
+ Whenever we zoom in or out, we need to adjust the scroll bars in
+ consequence. It would have been tempting to simply call
+
+ \snippet doc/src/snippets/code/doc_src_examples_imageviewer.cpp 4
+
+ but this would make the top-left corner the focal point, not the
+ center. Therefore we need to take into account the scroll bar
+ handle's size (the \l{QScrollBar::pageStep}{page step}).
+*/