/****************************************************************************+ −
**+ −
** Copyright (C) 2009 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}).+ −
*/+ −