Image Gestures Example▲
Sélectionnez
/**
**************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
***************************************************************************
*/
#include
"imagewidget.h"
#include <QtWidgets>
Q_LOGGING_CATEGORY(lcExample, "qt.examples.imagegestures"
)
ImageWidget::
ImageWidget(QWidget *
parent)
:
QWidget(parent),
position(0
),
horizontalOffset(0
),
verticalOffset(0
),
rotationAngle(0
),
scaleFactor(1
),
currentStepScaleFactor(1
)
{
setMinimumSize(QSize(100
,100
));
}
void
ImageWidget::
grabGestures(const
QList&
lt;Qt::
GestureType&
gt; &
amp;gestures)
{
foreach (Qt::
GestureType gesture, gestures)
grabGesture(gesture);
}
bool
ImageWidget::
event(QEvent *
event)
{
if
(event-&
gt;type() ==
QEvent::
Gesture)
return
gestureEvent(static_cast
&
lt;QGestureEvent*&
gt;(event));
return
QWidget::
event(event);
}
void
ImageWidget::
paintEvent(QPaintEvent*
)
{
QPainter p(this
);
const
qreal iw =
currentImage.width();
const
qreal ih =
currentImage.height();
const
qreal wh =
height();
const
qreal ww =
width();
p.translate(ww/
2
, wh/
2
);
p.translate(horizontalOffset, verticalOffset);
p.rotate(rotationAngle);
p.scale(currentStepScaleFactor *
scaleFactor, currentStepScaleFactor *
scaleFactor);
p.translate(-
iw/
2
, -
ih/
2
);
p.drawImage(0
, 0
, currentImage);
}
void
ImageWidget::
mouseDoubleClickEvent(QMouseEvent *
)
{
rotationAngle =
0
;
scaleFactor =
1
;
currentStepScaleFactor =
1
;
verticalOffset =
0
;
horizontalOffset =
0
;
update();
qCDebug(lcExample) &
lt;&
lt; "reset on mouse double click"
;
}
bool
ImageWidget::
gestureEvent(QGestureEvent *
event)
{
qCDebug(lcExample) &
lt;&
lt; "gestureEvent():"
&
lt;&
lt; event;
if
(QGesture *
swipe =
event-&
gt;gesture(Qt::
SwipeGesture))
swipeTriggered(static_cast
&
lt;QSwipeGesture *&
gt;(swipe));
else
if
(QGesture *
pan =
event-&
gt;gesture(Qt::
PanGesture))
panTriggered(static_cast
&
lt;QPanGesture *&
gt;(pan));
if
(QGesture *
pinch =
event-&
gt;gesture(Qt::
PinchGesture))
pinchTriggered(static_cast
&
lt;QPinchGesture *&
gt;(pinch));
return
true
;
}
void
ImageWidget::
panTriggered(QPanGesture *
gesture)
{
#ifndef QT_NO_CURSOR
switch
(gesture-&
gt;state()) {
case
Qt::
GestureStarted:
case
Qt::
GestureUpdated:
setCursor(Qt::
SizeAllCursor);
break
;
default
:
setCursor(Qt::
ArrowCursor);
}
#endif
QPointF delta =
gesture-&
gt;delta();
qCDebug(lcExample) &
lt;&
lt; "panTriggered():"
&
lt;&
lt; gesture;
horizontalOffset +=
delta.x();
verticalOffset +=
delta.y();
update();
}
void
ImageWidget::
pinchTriggered(QPinchGesture *
gesture)
{
QPinchGesture::
ChangeFlags changeFlags =
gesture-&
gt;changeFlags();
if
(changeFlags &
amp; QPinchGesture::
RotationAngleChanged) {
qreal rotationDelta =
gesture-&
gt;rotationAngle() -
gesture-&
gt;lastRotationAngle();
rotationAngle +=
rotationDelta;
qCDebug(lcExample) &
lt;&
lt; "pinchTriggered(): rotate by"
&
lt;&
lt;
rotationDelta &
lt;&
lt; "->"
&
lt;&
lt; rotationAngle;
}
if
(changeFlags &
amp; QPinchGesture::
ScaleFactorChanged) {
currentStepScaleFactor =
gesture-&
gt;totalScaleFactor();
qCDebug(lcExample) &
lt;&
lt; "pinchTriggered(): zoom by"
&
lt;&
lt;
gesture-&
gt;scaleFactor() &
lt;&
lt; "->"
&
lt;&
lt; currentStepScaleFactor;
}
if
(gesture-&
gt;state() ==
Qt::
GestureFinished) {
scaleFactor *=
currentStepScaleFactor;
currentStepScaleFactor =
1
;
}
update();
}
void
ImageWidget::
swipeTriggered(QSwipeGesture *
gesture)
{
if
(gesture-&
gt;state() ==
Qt::
GestureFinished) {
if
(gesture-&
gt;horizontalDirection() ==
QSwipeGesture::
Left
||
gesture-&
gt;verticalDirection() ==
QSwipeGesture::
Up) {
qCDebug(lcExample) &
lt;&
lt; "swipeTriggered(): swipe to previous"
;
goPrevImage();
}
else
{
qCDebug(lcExample) &
lt;&
lt; "swipeTriggered(): swipe to next"
;
goNextImage();
}
update();
}
}
void
ImageWidget::
resizeEvent(QResizeEvent*
)
{
update();
}
void
ImageWidget::
openDirectory(const
QString &
amp;path)
{
this
-&
gt;path =
path;
QDir dir(path);
QStringList nameFilters;
nameFilters &
lt;&
lt; "*.jpg"
&
lt;&
lt; "*.png"
;
files =
dir.entryList(nameFilters, QDir::
Files|
QDir::
Readable, QDir::
Name);
position =
0
;
goToImage(0
);
update();
}
QImage ImageWidget::
loadImage(const
QString &
amp;fileName)
{
QImageReader reader(fileName);
reader.setAutoTransform(true
);
qCDebug(lcExample) &
lt;&
lt; "loading"
&
lt;&
lt; QDir::
toNativeSeparators(fileName) &
lt;&
lt; position &
lt;&
lt; '/'
&
lt;&
lt; files.size();
if
(!
reader.canRead()) {
qCWarning(lcExample) &
lt;&
lt; QDir::
toNativeSeparators(fileName) &
lt;&
lt; ": can't load image"
;
return
QImage();
}
QImage image;
if
(!
reader.read(&
amp;image)) {
qCWarning(lcExample) &
lt;&
lt; QDir::
toNativeSeparators(fileName) &
lt;&
lt; ": corrupted image: "
&
lt;&
lt; reader.errorString();
return
QImage();
}
const
QSize maximumSize(2000
, 2000
); // Reduce in case someone has large photo images.
if
(image.size().width() &
gt; maximumSize.width() ||
image.height() &
gt; maximumSize.height())
image =
image.scaled(maximumSize, Qt::
KeepAspectRatio, Qt::
SmoothTransformation);
return
image;
}
void
ImageWidget::
goNextImage()
{
if
(files.isEmpty())
return
;
if
(position &
lt; files.size()-
1
) {
++
position;
prevImage =
currentImage;
currentImage =
nextImage;
if
(position+
1
&
lt; files.size())
nextImage =
loadImage(path +
QLatin1Char('/'
) +
files.at(position+
1
));
else
nextImage =
QImage();
}
update();
}
void
ImageWidget::
goPrevImage()
{
if
(files.isEmpty())
return
;
if
(position &
gt; 0
) {
--
position;
nextImage =
currentImage;
currentImage =
prevImage;
if
(position &
gt; 0
)
prevImage =
loadImage(path +
QLatin1Char('/'
) +
files.at(position-
1
));
else
prevImage =
QImage();
}
update();
}
void
ImageWidget::
goToImage(int
index)
{
if
(files.isEmpty())
return
;
if
(index &
lt; 0
||
index &
gt;=
files.size()) {
qCWarning(lcExample) &
lt;&
lt; "goToImage: invalid index: "
&
lt;&
lt; index;
return
;
}
if
(index ==
position+
1
) {
goNextImage();
return
;
}
if
(position &
gt; 0
&
amp;&
amp; index ==
position-
1
) {
goPrevImage();
return
;
}
position =
index;
if
(index &
gt; 0
)
prevImage =
loadImage(path +
QLatin1Char('/'
) +
files.at(position-
1
));
else
prevImage =
QImage();
currentImage =
loadImage(path +
QLatin1Char('/'
) +
files.at(position));
if
(position+
1
&
lt; files.size())
nextImage =
loadImage(path +
QLatin1Char('/'
) +
files.at(position+
1
));
else
nextImage =
QImage();
update();
}