Move image viewer example to manual test
Change-Id: I4b64033f1a075681ce5b918fdf2e018ad05a7869 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit b8f588bea74aae0a890e1af18b936b0bfbf8c237) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
d6bf951b76
commit
f61c424919
Binary file not shown.
Before Width: | Height: | Size: 83 KiB |
Binary file not shown.
Before Width: | Height: | Size: 143 KiB |
Binary file not shown.
Before Width: | Height: | Size: 60 KiB |
Binary file not shown.
Before Width: | Height: | Size: 83 KiB |
Binary file not shown.
Before Width: | Height: | Size: 84 KiB |
@ -1,320 +0,0 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
|
||||
|
||||
/*!
|
||||
\example widgets/imageviewer
|
||||
\title Image Viewer Example
|
||||
\ingroup examples-widgets
|
||||
\brief 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.
|
||||
|
||||
\borderedimage imageviewer-example.png
|
||||
\caption Screenshot of the Image Viewer example
|
||||
|
||||
With the Image Viewer application, the users can view an image of
|
||||
their choice. The \uicontrol File menu gives the user the possibility
|
||||
to:
|
||||
|
||||
\list
|
||||
\li \uicontrol{Open...} - Open an image file
|
||||
\li \uicontrol{Print...} - Print an image
|
||||
\li \uicontrol{Exit} - Exit the application
|
||||
\endlist
|
||||
|
||||
Once an image is loaded, the \uicontrol View menu allows the users to:
|
||||
|
||||
\list
|
||||
\li \uicontrol{Zoom In} - Scale the image up by 25%
|
||||
\li \uicontrol{Zoom Out} - Scale the image down by 25%
|
||||
\li \uicontrol{Normal Size} - Show the image at its original size
|
||||
\li \uicontrol{Fit to Window} - Stretch the image to occupy the entire window
|
||||
\endlist
|
||||
|
||||
In addition the \uicontrol Help menu provides the users with information
|
||||
about the Image Viewer example in particular, and about Qt in
|
||||
general.
|
||||
|
||||
\section1 ImageViewer Class Definition
|
||||
|
||||
\snippet 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 \uicontrol {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 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 \uicontrol {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 widgets/imageviewer/imageviewer.cpp 1
|
||||
|
||||
In the \c open() slot, we show a file dialog to the user. We compile
|
||||
a list of mime types for use as a filter by querying QImageReader
|
||||
for the available mime type names.
|
||||
|
||||
We show the file dialog until a valid file name is entered or
|
||||
the user cancels.
|
||||
|
||||
The function \c loadFile() is used to load the image.
|
||||
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 2
|
||||
|
||||
In the \c loadFile() function, we instantiate a QImageReader
|
||||
and enable automatic transformations by calling
|
||||
QImageReader::setAutoTransform(). For files in JPEG format,
|
||||
this ensures that portrait mode images of digital cameras are shown
|
||||
correctly by applying the appropriate orientation read from the
|
||||
EXIF meta data stored in the image file.
|
||||
|
||||
We then load the image using QImageReader::read(). If this returns
|
||||
a null image, indicating that the file is not an image file,
|
||||
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 \uicontrol OK button (the default) is
|
||||
sufficient, since the message is part of a normal operation.
|
||||
|
||||
\snippet 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 \uicontrol Print and \uicontrol {Fit to Window} menu entries and update
|
||||
the rest of the view menu entries. The \uicontrol Open and \uicontrol Exit
|
||||
entries are enabled by default.
|
||||
|
||||
If the \uicontrol {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
|
||||
|
||||
\code
|
||||
imageLabel->resize(imageLabel->pixmap()->size());
|
||||
\endcode
|
||||
|
||||
In the \c print() slot, we first make sure that an image has been
|
||||
loaded into the application:
|
||||
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 5
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 6
|
||||
|
||||
If the application is built in debug mode, the \c Q_ASSERT() macro
|
||||
will expand to
|
||||
|
||||
\code
|
||||
if (imageLabel->pixmap().isNull())
|
||||
qFatal("ASSERT: "imageLabel->pixmap().isNull()" in file ...");
|
||||
\endcode
|
||||
|
||||
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 \uicontrol qmake when building the application:
|
||||
|
||||
\code
|
||||
qmake "CONFIG += debug" foo.pro
|
||||
\endcode
|
||||
|
||||
or
|
||||
|
||||
\code
|
||||
qmake "CONFIG += release" foo.pro
|
||||
\endcode
|
||||
|
||||
Another approach is to add this line directly to the \c .pro
|
||||
file.
|
||||
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 7
|
||||
\snippet 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 widgets/imageviewer/imageviewer.cpp 9
|
||||
\snippet 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 \uicontrol {Zoom In}
|
||||
action and a \uicontrol {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
|
||||
\li \inlineimage imageviewer-original_size.png
|
||||
\li \inlineimage imageviewer-zoom_in_1.png
|
||||
\li \inlineimage imageviewer-zoom_in_2.png
|
||||
\endtable
|
||||
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 11
|
||||
\snippet 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 widgets/imageviewer/imageviewer.cpp 13
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 14
|
||||
|
||||
The \c fitToWindow() slot is called each time the user toggled
|
||||
the \uicontrol {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 \uicontrol {Zoom In}, \uicontrol {Zoom Out} and \uicontrol {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 \uicontrol {Fit to window} option turned on.
|
||||
Enlarging the window will stretch the image further, as shown in
|
||||
the third screenshot.
|
||||
|
||||
\table
|
||||
\row
|
||||
\li \inlineimage imageviewer-original_size.png
|
||||
\li \inlineimage imageviewer-fit_to_window_1.png
|
||||
\li \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 widgets/imageviewer/imageviewer.cpp 15
|
||||
\snippet 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 widgets/imageviewer/imageviewer.cpp 17
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 18
|
||||
|
||||
In the private \c createAction() function, we create the
|
||||
actions providing the application features and populate
|
||||
a menu with them.
|
||||
|
||||
We assign a short-cut key to each action and connect them to the
|
||||
appropriate slots. We only enable the \c openAct and \c exitAct 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}.
|
||||
|
||||
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 we put the menus in the \c {ImageViewer}'s
|
||||
menu bar which we retrieve with the QMainWindow::menuBar()
|
||||
function.
|
||||
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 21
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 22
|
||||
|
||||
The private \c updateActions() function enables or disables the
|
||||
\uicontrol {Zoom In}, \uicontrol {Zoom Out} and \uicontrol {Normal Size} menu
|
||||
entries depending on whether the \uicontrol {Fit to Window} option is
|
||||
turned on or off.
|
||||
|
||||
\snippet widgets/imageviewer/imageviewer.cpp 23
|
||||
\snippet 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 widgets/imageviewer/imageviewer.cpp 25
|
||||
\snippet 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
|
||||
|
||||
\code
|
||||
scrollBar->setValue(int(factor * scrollBar->value()));
|
||||
\endcode
|
||||
|
||||
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}).
|
||||
*/
|
@ -5,7 +5,6 @@ qt_internal_add_example(analogclock)
|
||||
qt_internal_add_example(calculator)
|
||||
qt_internal_add_example(calendarwidget)
|
||||
qt_internal_add_example(groupbox)
|
||||
qt_internal_add_example(imageviewer)
|
||||
qt_internal_add_example(lineedits)
|
||||
if(QT_FEATURE_movie)
|
||||
qt_internal_add_example(movie)
|
||||
|
@ -3,7 +3,6 @@ SUBDIRS = analogclock \
|
||||
calculator \
|
||||
calendarwidget \
|
||||
groupbox \
|
||||
imageviewer \
|
||||
lineedits \
|
||||
movie \
|
||||
scribble \
|
||||
|
@ -91,11 +91,7 @@ QT_BEGIN_NAMESPACE
|
||||
cause the size of the scroll area to be updated whenever the
|
||||
contents of the layout changes.
|
||||
|
||||
For a complete example using the QScrollArea class, see the \l
|
||||
{widgets/imageviewer}{Image Viewer} example. The example shows how
|
||||
to combine QLabel and QScrollArea to display an image.
|
||||
|
||||
\sa QAbstractScrollArea, QScrollBar, {Image Viewer Example}
|
||||
\sa QAbstractScrollArea, QScrollBar
|
||||
*/
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user