Pinch Zoom 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
"mouse.h"
#include <QGraphicsScene>
#include <QPainter>
#include <QRandomGenerator>
#include <QStyleOption>
#include <qmath.h>
const
qreal Pi =
M_PI;
const
qreal TwoPi =
2
*
M_PI;
static
qreal normalizeAngle(qreal angle)
{
while
(angle &
lt; 0
)
angle +=
TwoPi;
while
(angle &
gt; TwoPi)
angle -=
TwoPi;
return
angle;
}
Mouse::
Mouse()
:
angle(0
), speed(0
), mouseEyeDirection(0
),
color(QRandomGenerator::
global()-&
gt;bounded(256
), QRandomGenerator::
global()-&
gt;bounded(256
), QRandomGenerator::
global()-&
gt;bounded(256
))
{
setTransform(QTransform().rotate(QRandomGenerator::
global()-&
gt;bounded(360
*
16
)), true
);
startTimer(1000
/
33
);
}
QRectF Mouse::
boundingRect() const
{
qreal adjust =
0.5
;
return
QRectF(-
18
-
adjust, -
22
-
adjust,
36
+
adjust, 60
+
adjust);
}
QPainterPath Mouse::
shape() const
{
QPainterPath path;
path.addRect(-
10
, -
20
, 20
, 40
);
return
path;
}
void
Mouse::
paint(QPainter *
painter, const
QStyleOptionGraphicsItem *
, QWidget *
)
{
// Body
painter-&
gt;setBrush(color);
painter-&
gt;drawEllipse(-
10
, -
20
, 20
, 40
);
// Eyes
painter-&
gt;setBrush(Qt::
white);
painter-&
gt;drawEllipse(-
10
, -
17
, 8
, 8
);
painter-&
gt;drawEllipse(2
, -
17
, 8
, 8
);
// Nose
painter-&
gt;setBrush(Qt::
black);
painter-&
gt;drawEllipse(QRectF(-
2
, -
22
, 4
, 4
));
// Pupils
painter-&
gt;drawEllipse(QRectF(-
8.0
+
mouseEyeDirection, -
17
, 4
, 4
));
painter-&
gt;drawEllipse(QRectF(4.0
+
mouseEyeDirection, -
17
, 4
, 4
));
// Ears
painter-&
gt;setBrush(scene()-&
gt;collidingItems(this
).isEmpty() ? Qt::
darkYellow : Qt::
red);
painter-&
gt;drawEllipse(-
17
, -
12
, 16
, 16
);
painter-&
gt;drawEllipse(1
, -
12
, 16
, 16
);
// Tail
QPainterPath path(QPointF(0
, 20
));
path.cubicTo(-
5
, 22
, -
5
, 22
, 0
, 25
);
path.cubicTo(5
, 27
, 5
, 32
, 0
, 30
);
path.cubicTo(-
5
, 32
, -
5
, 42
, 0
, 35
);
painter-&
gt;setBrush(Qt::
NoBrush);
painter-&
gt;drawPath(path);
}
void
Mouse::
timerEvent(QTimerEvent *
)
{
// Don't move too far away
QLineF lineToCenter(QPointF(0
, 0
), mapFromScene(0
, 0
));
if
(lineToCenter.length() &
gt; 150
) {
qreal angleToCenter =
std::
atan2(lineToCenter.dy(), lineToCenter.dx());
angleToCenter =
normalizeAngle((Pi -
angleToCenter) +
Pi /
2
);
if
(angleToCenter &
lt; Pi &
amp;&
amp; angleToCenter &
gt; Pi /
4
) {
// Rotate left
angle +=
(angle &
lt; -
Pi /
2
) ? 0.25
: -
0.25
;
}
else
if
(angleToCenter &
gt;=
Pi &
amp;&
amp; angleToCenter &
lt; (Pi +
Pi /
2
+
Pi /
4
)) {
// Rotate right
angle +=
(angle &
lt; Pi /
2
) ? 0.25
: -
0.25
;
}
}
else
if
(::
sin(angle) &
lt; 0
) {
angle +=
0.25
;
}
else
if
(::
sin(angle) &
gt; 0
) {
angle -=
0.25
;
}
// Try not to crash with any other mice
QList&
lt;QGraphicsItem *&
gt; dangerMice =
scene()-&
gt;items(QPolygonF()
&
lt;&
lt; mapToScene(0
, 0
)
&
lt;&
lt; mapToScene(-
30
, -
50
)
&
lt;&
lt; mapToScene(30
, -
50
));
foreach (QGraphicsItem *
item, dangerMice) {
if
(item ==
this
)
continue
;
QLineF lineToMouse(QPointF(0
, 0
), mapFromItem(item, 0
, 0
));
qreal angleToMouse =
std::
atan2(lineToMouse.dy(), lineToMouse.dx());
angleToMouse =
normalizeAngle((Pi -
angleToMouse) +
Pi /
2
);
if
(angleToMouse &
gt;=
0
&
amp;&
amp; angleToMouse &
lt; Pi /
2
) {
// Rotate right
angle +=
0.5
;
}
else
if
(angleToMouse &
lt;=
TwoPi &
amp;&
amp; angleToMouse &
gt; (TwoPi -
Pi /
2
)) {
// Rotate left
angle -=
0.5
;
}
}
// Add some random movement
if
(dangerMice.size() &
gt; 1
&
amp;&
amp; QRandomGenerator::
global()-&
gt;bounded(10
) ==
0
) {
if
(QRandomGenerator::
global()-&
gt;bounded(1
))
angle +=
QRandomGenerator::
global()-&
gt;bounded(1
/
500.0
);
else
angle -=
QRandomGenerator::
global()-&
gt;bounded(1
/
500.0
);
}
speed +=
(-
50
+
QRandomGenerator::
global()-&
gt;bounded(100
)) /
100.0
;
qreal dx =
::
sin(angle) *
10
;
mouseEyeDirection =
(qAbs(dx /
5
) &
lt; 1
) ? 0
: dx /
5
;
setTransform(QTransform().rotate(dx), true
);
setPos(mapToParent(0
, -
(3
+
sin(speed) *
3
)));
}