Pad Navigator 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
"flippablepad.h"
#include
"padnavigator.h"
#include
"splashitem.h"
#ifndef QT_NO_OPENGL
#include <QtOpenGL>
#else
#include <QtWidgets>
#endif
PadNavigator::
PadNavigator(const
QSize &
amp;size, QWidget *
parent)
:
QGraphicsView(parent)
{
// Splash item
SplashItem *
splash =
new
SplashItem;
splash-&
gt;setZValue(1
);
// Pad item
FlippablePad *
pad =
new
FlippablePad(size);
QGraphicsRotation *
flipRotation =
new
QGraphicsRotation(pad);
QGraphicsRotation *
xRotation =
new
QGraphicsRotation(pad);
QGraphicsRotation *
yRotation =
new
QGraphicsRotation(pad);
flipRotation-&
gt;setAxis(Qt::
YAxis);
xRotation-&
gt;setAxis(Qt::
YAxis);
yRotation-&
gt;setAxis(Qt::
XAxis);
pad-&
gt;setTransformations(QList&
lt;QGraphicsTransform *&
gt;()
&
lt;&
lt; flipRotation
&
lt;&
lt; xRotation &
lt;&
lt; yRotation);
// Back (proxy widget) item
QGraphicsProxyWidget *
backItem =
new
QGraphicsProxyWidget(pad);
QWidget *
widget =
new
QWidget;
form.setupUi(widget);
form.hostName-&
gt;setFocus();
backItem-&
gt;setWidget(widget);
backItem-&
gt;setVisible(false
);
backItem-&
gt;setFocus();
backItem-&
gt;setCacheMode(QGraphicsItem::
ItemCoordinateCache);
const
QRectF r =
backItem-&
gt;rect();
backItem-&
gt;setTransform(QTransform()
.rotate(180
, Qt::
YAxis)
.translate(-
r.width()/
2
, -
r.height()/
2
));
// Selection item
RoundRectItem *
selectionItem =
new
RoundRectItem(QRectF(-
60
, -
60
, 120
, 120
), Qt::
gray, pad);
selectionItem-&
gt;setZValue(0.5
);
// Splash animations
QPropertyAnimation *
smoothSplashMove =
new
QPropertyAnimation(splash, "y"
);
QPropertyAnimation *
smoothSplashOpacity =
new
QPropertyAnimation(splash, "opacity"
);
smoothSplashMove-&
gt;setEasingCurve(QEasingCurve::
InQuad);
smoothSplashMove-&
gt;setDuration(250
);
smoothSplashOpacity-&
gt;setDuration(250
);
// Selection animation
QPropertyAnimation *
smoothXSelection =
new
QPropertyAnimation(selectionItem, "x"
);
QPropertyAnimation *
smoothYSelection =
new
QPropertyAnimation(selectionItem, "y"
);
QPropertyAnimation *
smoothXRotation =
new
QPropertyAnimation(xRotation, "angle"
);
QPropertyAnimation *
smoothYRotation =
new
QPropertyAnimation(yRotation, "angle"
);
smoothXSelection-&
gt;setDuration(125
);
smoothYSelection-&
gt;setDuration(125
);
smoothXRotation-&
gt;setDuration(125
);
smoothYRotation-&
gt;setDuration(125
);
smoothXSelection-&
gt;setEasingCurve(QEasingCurve::
InOutQuad);
smoothYSelection-&
gt;setEasingCurve(QEasingCurve::
InOutQuad);
smoothXRotation-&
gt;setEasingCurve(QEasingCurve::
InOutQuad);
smoothYRotation-&
gt;setEasingCurve(QEasingCurve::
InOutQuad);
// Flip animation setup
QPropertyAnimation *
smoothFlipRotation =
new
QPropertyAnimation(flipRotation, "angle"
);
QPropertyAnimation *
smoothFlipScale =
new
QPropertyAnimation(pad, "scale"
);
QPropertyAnimation *
smoothFlipXRotation =
new
QPropertyAnimation(xRotation, "angle"
);
QPropertyAnimation *
smoothFlipYRotation =
new
QPropertyAnimation(yRotation, "angle"
);
QParallelAnimationGroup *
flipAnimation =
new
QParallelAnimationGroup(this
);
smoothFlipScale-&
gt;setDuration(500
);
smoothFlipRotation-&
gt;setDuration(500
);
smoothFlipXRotation-&
gt;setDuration(500
);
smoothFlipYRotation-&
gt;setDuration(500
);
smoothFlipScale-&
gt;setEasingCurve(QEasingCurve::
InOutQuad);
smoothFlipRotation-&
gt;setEasingCurve(QEasingCurve::
InOutQuad);
smoothFlipXRotation-&
gt;setEasingCurve(QEasingCurve::
InOutQuad);
smoothFlipYRotation-&
gt;setEasingCurve(QEasingCurve::
InOutQuad);
smoothFlipScale-&
gt;setKeyValueAt(0
, qvariant_cast&
lt;qreal&
gt;(1.0
));
smoothFlipScale-&
gt;setKeyValueAt(0.5
, qvariant_cast&
lt;qreal&
gt;(0.7
));
smoothFlipScale-&
gt;setKeyValueAt(1
, qvariant_cast&
lt;qreal&
gt;(1.0
));
flipAnimation-&
gt;addAnimation(smoothFlipRotation);
flipAnimation-&
gt;addAnimation(smoothFlipScale);
flipAnimation-&
gt;addAnimation(smoothFlipXRotation);
flipAnimation-&
gt;addAnimation(smoothFlipYRotation);
// Flip animation delayed property assignment
QSequentialAnimationGroup *
setVariablesSequence =
new
QSequentialAnimationGroup;
QPropertyAnimation *
setFillAnimation =
new
QPropertyAnimation(pad, "fill"
);
QPropertyAnimation *
setBackItemVisibleAnimation =
new
QPropertyAnimation(backItem, "visible"
);
QPropertyAnimation *
setSelectionItemVisibleAnimation =
new
QPropertyAnimation(selectionItem, "visible"
);
setFillAnimation-&
gt;setDuration(0
);
setBackItemVisibleAnimation-&
gt;setDuration(0
);
setSelectionItemVisibleAnimation-&
gt;setDuration(0
);
setVariablesSequence-&
gt;addPause(250
);
setVariablesSequence-&
gt;addAnimation(setBackItemVisibleAnimation);
setVariablesSequence-&
gt;addAnimation(setSelectionItemVisibleAnimation);
setVariablesSequence-&
gt;addAnimation(setFillAnimation);
flipAnimation-&
gt;addAnimation(setVariablesSequence);
// Build the state machine
QStateMachine *
stateMachine =
new
QStateMachine(this
);
QState *
splashState =
new
QState(stateMachine);
QState *
frontState =
new
QState(stateMachine);
QHistoryState *
historyState =
new
QHistoryState(frontState);
QState *
backState =
new
QState(stateMachine);
frontState-&
gt;assignProperty(pad, "fill"
, false
);
frontState-&
gt;assignProperty(splash, "opacity"
, 0.0
);
frontState-&
gt;assignProperty(backItem, "visible"
, false
);
frontState-&
gt;assignProperty(flipRotation, "angle"
, qvariant_cast&
lt;qreal&
gt;(0.0
));
frontState-&
gt;assignProperty(selectionItem, "visible"
, true
);
backState-&
gt;assignProperty(pad, "fill"
, true
);
backState-&
gt;assignProperty(backItem, "visible"
, true
);
backState-&
gt;assignProperty(xRotation, "angle"
, qvariant_cast&
lt;qreal&
gt;(0.0
));
backState-&
gt;assignProperty(yRotation, "angle"
, qvariant_cast&
lt;qreal&
gt;(0.0
));
backState-&
gt;assignProperty(flipRotation, "angle"
, qvariant_cast&
lt;qreal&
gt;(180.0
));
backState-&
gt;assignProperty(selectionItem, "visible"
, false
);
stateMachine-&
gt;addDefaultAnimation(smoothXRotation);
stateMachine-&
gt;addDefaultAnimation(smoothYRotation);
stateMachine-&
gt;addDefaultAnimation(smoothXSelection);
stateMachine-&
gt;addDefaultAnimation(smoothYSelection);
stateMachine-&
gt;setInitialState(splashState);
// Transitions
QEventTransition *
anyKeyTransition =
new
QEventTransition(this
, QEvent::
KeyPress, splashState);
anyKeyTransition-&
gt;setTargetState(frontState);
anyKeyTransition-&
gt;addAnimation(smoothSplashMove);
anyKeyTransition-&
gt;addAnimation(smoothSplashOpacity);
QKeyEventTransition *
enterTransition =
new
QKeyEventTransition(this
, QEvent::
KeyPress,
Qt::
Key_Enter, backState);
QKeyEventTransition *
returnTransition =
new
QKeyEventTransition(this
, QEvent::
KeyPress,
Qt::
Key_Return, backState);
QKeyEventTransition *
backEnterTransition =
new
QKeyEventTransition(this
, QEvent::
KeyPress,
Qt::
Key_Enter, frontState);
QKeyEventTransition *
backReturnTransition =
new
QKeyEventTransition(this
, QEvent::
KeyPress,
Qt::
Key_Return, frontState);
enterTransition-&
gt;setTargetState(historyState);
returnTransition-&
gt;setTargetState(historyState);
backEnterTransition-&
gt;setTargetState(backState);
backReturnTransition-&
gt;setTargetState(backState);
enterTransition-&
gt;addAnimation(flipAnimation);
returnTransition-&
gt;addAnimation(flipAnimation);
backEnterTransition-&
gt;addAnimation(flipAnimation);
backReturnTransition-&
gt;addAnimation(flipAnimation);
// Create substates for each icon; store in temporary grid.
int
columns =
size.width();
int
rows =
size.height();
QVector&
lt; QVector&
lt; QState *
&
gt; &
gt; stateGrid;
stateGrid.resize(rows);
for
(int
y =
0
; y &
lt; rows; ++
y) {
stateGrid[y].resize(columns);
for
(int
x =
0
; x &
lt; columns; ++
x)
stateGrid[y][x] =
new
QState(frontState);
}
frontState-&
gt;setInitialState(stateGrid[0
][0
]);
selectionItem-&
gt;setPos(pad-&
gt;iconAt(0
, 0
)-&
gt;pos());
// Enable key navigation using state transitions
for
(int
y =
0
; y &
lt; rows; ++
y) {
for
(int
x =
0
; x &
lt; columns; ++
x) {
QState *
state =
stateGrid[y][x];
QKeyEventTransition *
rightTransition =
new
QKeyEventTransition(this
, QEvent::
KeyPress,
Qt::
Key_Right, state);
QKeyEventTransition *
leftTransition =
new
QKeyEventTransition(this
, QEvent::
KeyPress,
Qt::
Key_Left, state);
QKeyEventTransition *
downTransition =
new
QKeyEventTransition(this
, QEvent::
KeyPress,
Qt::
Key_Down, state);
QKeyEventTransition *
upTransition =
new
QKeyEventTransition(this
, QEvent::
KeyPress,
Qt::
Key_Up, state);
rightTransition-&
gt;setTargetState(stateGrid[y][(x +
1
) %
columns]);
leftTransition-&
gt;setTargetState(stateGrid[y][((x -
1
) +
columns) %
columns]);
downTransition-&
gt;setTargetState(stateGrid[(y +
1
) %
rows][x]);
upTransition-&
gt;setTargetState(stateGrid[((y -
1
) +
rows) %
rows][x]);
RoundRectItem *
icon =
pad-&
gt;iconAt(x, y);
state-&
gt;assignProperty(xRotation, "angle"
, -
icon-&
gt;x() /
6.0
);
state-&
gt;assignProperty(yRotation, "angle"
, icon-&
gt;y() /
6.0
);
state-&
gt;assignProperty(selectionItem, "x"
, icon-&
gt;x());
state-&
gt;assignProperty(selectionItem, "y"
, icon-&
gt;y());
frontState-&
gt;assignProperty(icon, "visible"
, true
);
backState-&
gt;assignProperty(icon, "visible"
, false
);
QPropertyAnimation *
setIconVisibleAnimation =
new
QPropertyAnimation(icon, "visible"
);
setIconVisibleAnimation-&
gt;setDuration(0
);
setVariablesSequence-&
gt;addAnimation(setIconVisibleAnimation);
}
}
// Scene
QGraphicsScene *
scene =
new
QGraphicsScene(this
);
scene-&
gt;setBackgroundBrush(QPixmap(":/images/blue_angle_swirl.jpg"
));
scene-&
gt;setItemIndexMethod(QGraphicsScene::
NoIndex);
scene-&
gt;addItem(pad);
scene-&
gt;setSceneRect(scene-&
gt;itemsBoundingRect());
setScene(scene);
// Adjust splash item to scene contents
const
QRectF sbr =
splash-&
gt;boundingRect();
splash-&
gt;setPos(-
sbr.width() /
2
, scene-&
gt;sceneRect().top() -
2
);
frontState-&
gt;assignProperty(splash, "y"
, splash-&
gt;y() -
100.0
);
scene-&
gt;addItem(splash);
// View
setVerticalScrollBarPolicy(Qt::
ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::
ScrollBarAlwaysOff);
setMinimumSize(50
, 50
);
setViewportUpdateMode(FullViewportUpdate);
setCacheMode(CacheBackground);
setRenderHints(QPainter::
Antialiasing
|
QPainter::
SmoothPixmapTransform
|
QPainter::
TextAntialiasing);
#ifndef QT_NO_OPENGL
setViewport(new
QOpenGLWidget);
#endif
stateMachine-&
gt;start();
}
void
PadNavigator::
resizeEvent(QResizeEvent *
event)
{
QGraphicsView::
resizeEvent(event);
fitInView(scene()-&
gt;sceneRect(), Qt::
KeepAspectRatio);
}