diff -r dee5afe5301f -r 3f74d0d4af4c doc/src/examples/imageviewer.qdoc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/src/examples/imageviewer.qdoc Thu Apr 08 14:19:33 2010 +0300 @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** 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.qdoc 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.qdoc 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.qdoc 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}). +*/