diff options
Diffstat (limited to 'examples/animation')
55 files changed, 3188 insertions, 0 deletions
diff --git a/examples/animation/README b/examples/animation/README new file mode 100644 index 0000000000..6a892f8655 --- /dev/null +++ b/examples/animation/README @@ -0,0 +1,38 @@ +The animation framework aims to provide an easy way for creating animated and +smooth GUI's. By animating Qt properties, the framework provides great freedom +for animating widgets and other QObjects. The framework can also be used with +the Graphics View framework. + +The example launcher provided with Qt can be used to explore each of the +examples in this directory. + +Documentation for these examples can be found via the Tutorial and Examples +link in the main Qt documentation. + + +Finding the Qt Examples and Demos launcher +========================================== + +On Windows: + +The launcher can be accessed via the Windows Start menu. Select the menu +entry entitled "Qt Examples and Demos" entry in the submenu containing +the Qt tools. + +On Mac OS X: + +For the binary distribution, the qtdemo executable is installed in the +/Developer/Applications/Qt directory. For the source distribution, it is +installed alongside the other Qt tools on the path specified when Qt is +configured. + +On Unix/Linux: + +The qtdemo executable is installed alongside the other Qt tools on the path +specified when Qt is configured. + +On all platforms: + +The source code for the launcher can be found in the demos/qtdemo directory +in the Qt package. This example is built at the same time as the Qt libraries, +tools, examples, and demonstrations. diff --git a/examples/animation/animatedtiles/animatedtiles.pro b/examples/animation/animatedtiles/animatedtiles.pro new file mode 100644 index 0000000000..66a54edc05 --- /dev/null +++ b/examples/animation/animatedtiles/animatedtiles.pro @@ -0,0 +1,13 @@ +SOURCES = main.cpp +RESOURCES = animatedtiles.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/animatedtiles +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS animatedtiles.pro images +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/animatedtiles +INSTALLS += target sources + +symbian { + TARGET.UID3 = 0xA000D7D1 + include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +} diff --git a/examples/animation/animatedtiles/animatedtiles.qrc b/examples/animation/animatedtiles/animatedtiles.qrc new file mode 100644 index 0000000000..c43a979723 --- /dev/null +++ b/examples/animation/animatedtiles/animatedtiles.qrc @@ -0,0 +1,11 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>images/Time-For-Lunch-2.jpg</file> + <file>images/centered.png</file> + <file>images/ellipse.png</file> + <file>images/figure8.png</file> + <file>images/kinetic.png</file> + <file>images/random.png</file> + <file>images/tile.png</file> +</qresource> +</RCC> diff --git a/examples/animation/animatedtiles/images/Time-For-Lunch-2.jpg b/examples/animation/animatedtiles/images/Time-For-Lunch-2.jpg Binary files differnew file mode 100644 index 0000000000..c57a555490 --- /dev/null +++ b/examples/animation/animatedtiles/images/Time-For-Lunch-2.jpg diff --git a/examples/animation/animatedtiles/images/centered.png b/examples/animation/animatedtiles/images/centered.png Binary files differnew file mode 100644 index 0000000000..e416156a0e --- /dev/null +++ b/examples/animation/animatedtiles/images/centered.png diff --git a/examples/animation/animatedtiles/images/ellipse.png b/examples/animation/animatedtiles/images/ellipse.png Binary files differnew file mode 100644 index 0000000000..2c3ba881c5 --- /dev/null +++ b/examples/animation/animatedtiles/images/ellipse.png diff --git a/examples/animation/animatedtiles/images/figure8.png b/examples/animation/animatedtiles/images/figure8.png Binary files differnew file mode 100644 index 0000000000..6b058041c4 --- /dev/null +++ b/examples/animation/animatedtiles/images/figure8.png diff --git a/examples/animation/animatedtiles/images/kinetic.png b/examples/animation/animatedtiles/images/kinetic.png Binary files differnew file mode 100644 index 0000000000..55cfa5515f --- /dev/null +++ b/examples/animation/animatedtiles/images/kinetic.png diff --git a/examples/animation/animatedtiles/images/random.png b/examples/animation/animatedtiles/images/random.png Binary files differnew file mode 100644 index 0000000000..415d96f856 --- /dev/null +++ b/examples/animation/animatedtiles/images/random.png diff --git a/examples/animation/animatedtiles/images/tile.png b/examples/animation/animatedtiles/images/tile.png Binary files differnew file mode 100644 index 0000000000..c8f39d8d40 --- /dev/null +++ b/examples/animation/animatedtiles/images/tile.png diff --git a/examples/animation/animatedtiles/main.cpp b/examples/animation/animatedtiles/main.cpp new file mode 100644 index 0000000000..1badb4f3ef --- /dev/null +++ b/examples/animation/animatedtiles/main.cpp @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 <QtGui> +#include <QtCore/qstate.h> + +class Pixmap : public QObject, public QGraphicsPixmapItem +{ + Q_OBJECT + Q_PROPERTY(QPointF pos READ pos WRITE setPos) +public: + Pixmap(const QPixmap &pix) + : QObject(), QGraphicsPixmapItem(pix) + { + setCacheMode(DeviceCoordinateCache); + } +}; + +class Button : public QGraphicsWidget +{ + Q_OBJECT +public: + Button(const QPixmap &pixmap, QGraphicsItem *parent = 0) + : QGraphicsWidget(parent), _pix(pixmap) + { + setAcceptHoverEvents(true); + setCacheMode(DeviceCoordinateCache); + } + + QRectF boundingRect() const + { + return QRectF(-65, -65, 130, 130); + } + + QPainterPath shape() const + { + QPainterPath path; + path.addEllipse(boundingRect()); + return path; + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) + { + bool down = option->state & QStyle::State_Sunken; + QRectF r = boundingRect(); + QLinearGradient grad(r.topLeft(), r.bottomRight()); + grad.setColorAt(down ? 1 : 0, option->state & QStyle::State_MouseOver ? Qt::white : Qt::lightGray); + grad.setColorAt(down ? 0 : 1, Qt::darkGray); + painter->setPen(Qt::darkGray); + painter->setBrush(grad); + painter->drawEllipse(r); + QLinearGradient grad2(r.topLeft(), r.bottomRight()); + grad.setColorAt(down ? 1 : 0, Qt::darkGray); + grad.setColorAt(down ? 0 : 1, Qt::lightGray); + painter->setPen(Qt::NoPen); + painter->setBrush(grad); + if (down) + painter->translate(2, 2); + painter->drawEllipse(r.adjusted(5, 5, -5, -5)); + painter->drawPixmap(-_pix.width()/2, -_pix.height()/2, _pix); + } + +signals: + void pressed(); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *) + { + emit pressed(); + update(); + } + + void mouseReleaseEvent(QGraphicsSceneMouseEvent *) + { + update(); + } + +private: + QPixmap _pix; +}; + +class View : public QGraphicsView +{ +public: + View(QGraphicsScene *scene) : QGraphicsView(scene) { } + +protected: + void resizeEvent(QResizeEvent *event) + { + QGraphicsView::resizeEvent(event); + fitInView(sceneRect(), Qt::KeepAspectRatio); + } +}; + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(animatedtiles); + + QApplication app(argc, argv); + + QPixmap kineticPix(":/images/kinetic.png"); + QPixmap bgPix(":/images/Time-For-Lunch-2.jpg"); + + QGraphicsScene scene(-350, -350, 700, 700); + + QList<Pixmap *> items; + for (int i = 0; i < 64; ++i) { + Pixmap *item = new Pixmap(kineticPix); + item->setOffset(-kineticPix.width()/2, -kineticPix.height()/2); + item->setZValue(i); + items << item; + scene.addItem(item); + } + + // Buttons + QGraphicsItem *buttonParent = new QGraphicsRectItem; + Button *ellipseButton = new Button(QPixmap(":/images/ellipse.png"), buttonParent); + Button *figure8Button = new Button(QPixmap(":/images/figure8.png"), buttonParent); + Button *randomButton = new Button(QPixmap(":/images/random.png"), buttonParent); + Button *tiledButton = new Button(QPixmap(":/images/tile.png"), buttonParent); + Button *centeredButton = new Button(QPixmap(":/images/centered.png"), buttonParent); + + ellipseButton->setPos(-100, -100); + figure8Button->setPos(100, -100); + randomButton->setPos(0, 0); + tiledButton->setPos(-100, 100); + centeredButton->setPos(100, 100); + + scene.addItem(buttonParent); + buttonParent->scale(0.75, 0.75); + buttonParent->setPos(200, 200); + buttonParent->setZValue(65); + + // States + QState *rootState = new QState; + QState *ellipseState = new QState(rootState); + QState *figure8State = new QState(rootState); + QState *randomState = new QState(rootState); + QState *tiledState = new QState(rootState); + QState *centeredState = new QState(rootState); + + // Values + for (int i = 0; i < items.count(); ++i) { + Pixmap *item = items.at(i); + // Ellipse + ellipseState->assignProperty(item, "pos", + QPointF(cos((i / 63.0) * 6.28) * 250, + sin((i / 63.0) * 6.28) * 250)); + + // Figure 8 + figure8State->assignProperty(item, "pos", + QPointF(sin((i / 63.0) * 6.28) * 250, + sin(((i * 2)/63.0) * 6.28) * 250)); + + // Random + randomState->assignProperty(item, "pos", + QPointF(-250 + qrand() % 500, + -250 + qrand() % 500)); + + // Tiled + tiledState->assignProperty(item, "pos", + QPointF(((i % 8) - 4) * kineticPix.width() + kineticPix.width() / 2, + ((i / 8) - 4) * kineticPix.height() + kineticPix.height() / 2)); + + // Centered + centeredState->assignProperty(item, "pos", QPointF()); + } + + // Ui + View *view = new View(&scene); + view->setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Animated Tiles")); + view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view->setBackgroundBrush(bgPix); + view->setCacheMode(QGraphicsView::CacheBackground); + view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + view->show(); + + QStateMachine states; + states.addState(rootState); + states.setInitialState(rootState); + rootState->setInitialState(centeredState); + + QParallelAnimationGroup *group = new QParallelAnimationGroup; + for (int i = 0; i < items.count(); ++i) { + QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); + anim->setDuration(750 + i * 25); + anim->setEasingCurve(QEasingCurve::InOutBack); + group->addAnimation(anim); + } + QAbstractTransition *trans = rootState->addTransition(ellipseButton, SIGNAL(pressed()), ellipseState); + trans->addAnimation(group); + + trans = rootState->addTransition(figure8Button, SIGNAL(pressed()), figure8State); + trans->addAnimation(group); + + trans = rootState->addTransition(randomButton, SIGNAL(pressed()), randomState); + trans->addAnimation(group); + + trans = rootState->addTransition(tiledButton, SIGNAL(pressed()), tiledState); + trans->addAnimation(group); + + trans = rootState->addTransition(centeredButton, SIGNAL(pressed()), centeredState); + trans->addAnimation(group); + + QTimer timer; + timer.start(125); + timer.setSingleShot(true); + trans = rootState->addTransition(&timer, SIGNAL(timeout()), ellipseState); + trans->addAnimation(group); + + states.start(); + +#ifdef QT_KEYPAD_NAVIGATION + QApplication::setNavigationMode(Qt::NavigationModeCursorAuto); +#endif + return app.exec(); +} + +#include "main.moc" diff --git a/examples/animation/animation.pro b/examples/animation/animation.pro new file mode 100644 index 0000000000..4a9064d97e --- /dev/null +++ b/examples/animation/animation.pro @@ -0,0 +1,15 @@ +TEMPLATE = \ + subdirs +SUBDIRS += \ + animatedtiles \ + appchooser \ + easing \ + moveblocks \ + states \ + stickman \ + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS animation.pro README +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation +INSTALLS += target sources diff --git a/examples/animation/appchooser/accessories-dictionary.png b/examples/animation/appchooser/accessories-dictionary.png Binary files differnew file mode 100644 index 0000000000..e9bd55d918 --- /dev/null +++ b/examples/animation/appchooser/accessories-dictionary.png diff --git a/examples/animation/appchooser/akregator.png b/examples/animation/appchooser/akregator.png Binary files differnew file mode 100644 index 0000000000..a086f45ab6 --- /dev/null +++ b/examples/animation/appchooser/akregator.png diff --git a/examples/animation/appchooser/appchooser.pro b/examples/animation/appchooser/appchooser.pro new file mode 100644 index 0000000000..d4599db840 --- /dev/null +++ b/examples/animation/appchooser/appchooser.pro @@ -0,0 +1,13 @@ +SOURCES = main.cpp +RESOURCES = appchooser.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/appchooser +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS appchooser.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/appchooser +INSTALLS += target sources + +symbian { + TARGET.UID3 = 0xA000E3F5 + include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +} diff --git a/examples/animation/appchooser/appchooser.qrc b/examples/animation/appchooser/appchooser.qrc new file mode 100644 index 0000000000..28a3e1c4c1 --- /dev/null +++ b/examples/animation/appchooser/appchooser.qrc @@ -0,0 +1,8 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>accessories-dictionary.png</file> + <file>akregator.png</file> + <file>digikam.png</file> + <file>k3b.png</file> +</qresource> +</RCC> diff --git a/examples/animation/appchooser/digikam.png b/examples/animation/appchooser/digikam.png Binary files differnew file mode 100644 index 0000000000..9de9fb2f80 --- /dev/null +++ b/examples/animation/appchooser/digikam.png diff --git a/examples/animation/appchooser/k3b.png b/examples/animation/appchooser/k3b.png Binary files differnew file mode 100644 index 0000000000..bbcafcfba1 --- /dev/null +++ b/examples/animation/appchooser/k3b.png diff --git a/examples/animation/appchooser/main.cpp b/examples/animation/appchooser/main.cpp new file mode 100644 index 0000000000..86ec073f6e --- /dev/null +++ b/examples/animation/appchooser/main.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 <QtCore> +#include <QtGui> + + +class Pixmap : public QGraphicsWidget +{ + Q_OBJECT + +public: + Pixmap(const QPixmap &pix, QGraphicsItem *parent = 0) + : QGraphicsWidget(parent), orig(pix), p(pix) + { + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + { + painter->drawPixmap(QPointF(), p); + } + + virtual void mousePressEvent(QGraphicsSceneMouseEvent * ) + { + emit clicked(); + } + + virtual void setGeometry(const QRectF &rect) + { + QGraphicsWidget::setGeometry(rect); + + if (rect.size().width() > orig.size().width()) + p = orig.scaled(rect.size().toSize()); + else + p = orig; + } + +Q_SIGNALS: + void clicked(); + +private: + QPixmap orig; + QPixmap p; +}; + +void createStates(const QObjectList &objects, + const QRect &selectedRect, QState *parent) +{ + for (int i = 0; i < objects.size(); ++i) { + QState *state = new QState(parent); + state->assignProperty(objects.at(i), "geometry", selectedRect); + parent->addTransition(objects.at(i), SIGNAL(clicked()), state); + } +} + +void createAnimations(const QObjectList &objects, QStateMachine *machine) +{ + for (int i=0; i<objects.size(); ++i) + machine->addDefaultAnimation(new QPropertyAnimation(objects.at(i), "geometry")); +} + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(appchooser); + + QApplication app(argc, argv); + + Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png")); + Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png")); + Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png")); + Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png")); + + p1->setObjectName("p1"); + p2->setObjectName("p2"); + p3->setObjectName("p3"); + p4->setObjectName("p4"); + + p1->setGeometry(QRectF(0.0, 0.0, 64.0, 64.0)); + p2->setGeometry(QRectF(236.0, 0.0, 64.0, 64.0)); + p3->setGeometry(QRectF(236.0, 236.0, 64.0, 64.0)); + p4->setGeometry(QRectF(0.0, 236.0, 64.0, 64.0)); + + QGraphicsScene scene(0, 0, 300, 300); + scene.setBackgroundBrush(Qt::white); + scene.addItem(p1); + scene.addItem(p2); + scene.addItem(p3); + scene.addItem(p4); + + QGraphicsView window(&scene); + window.setFrameStyle(0); + window.setAlignment(Qt::AlignLeft | Qt::AlignTop); + window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + QStateMachine machine; + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); + + QState *group = new QState(&machine); + group->setObjectName("group"); + QRect selectedRect(86, 86, 128, 128); + + QState *idleState = new QState(group); + group->setInitialState(idleState); + + QObjectList objects; + objects << p1 << p2 << p3 << p4; + createStates(objects, selectedRect, group); + createAnimations(objects, &machine); + + machine.setInitialState(group); + machine.start(); + + window.resize(300, 300); + window.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/animation/easing/animation.h b/examples/animation/easing/animation.h new file mode 100644 index 0000000000..f0aef6560b --- /dev/null +++ b/examples/animation/easing/animation.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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$ +** +****************************************************************************/ + +#ifndef ANIMATION_H +#define ANIMATION_H + +#include <QtGui> + +#include <QtCore/qpropertyanimation.h> + +class Animation : public QPropertyAnimation { +public: + enum PathType { + LinearPath, + CirclePath, + NPathTypes + }; + Animation(QObject *target, const QByteArray &prop) + : QPropertyAnimation(target, prop) + { + setPathType(LinearPath); + } + + void setPathType(PathType pathType) + { + if (pathType >= NPathTypes) + qWarning("Unknown pathType %d", pathType); + + m_pathType = pathType; + m_path = QPainterPath(); + } + + void updateCurrentTime(int currentTime) + { + if (m_pathType == CirclePath) { + if (m_path.isEmpty()) { + QPointF to = endValue().toPointF(); + QPointF from = startValue().toPointF(); + m_path.moveTo(from); + m_path.addEllipse(QRectF(from, to)); + } + int dura = duration(); + const qreal progress = ((dura == 0) ? 1 : ((((currentTime - 1) % dura) + 1) / qreal(dura))); + + qreal easedProgress = easingCurve().valueForProgress(progress); + if (easedProgress > 1.0) { + easedProgress -= 1.0; + } else if (easedProgress < 0) { + easedProgress += 1.0; + } + QPointF pt = m_path.pointAtPercent(easedProgress); + updateCurrentValue(pt); + emit valueChanged(pt); + } else { + QPropertyAnimation::updateCurrentTime(currentTime); + } + } + + QPainterPath m_path; + PathType m_pathType; +}; + +#endif // ANIMATION_H diff --git a/examples/animation/easing/easing.pro b/examples/animation/easing/easing.pro new file mode 100644 index 0000000000..4715f2c826 --- /dev/null +++ b/examples/animation/easing/easing.pro @@ -0,0 +1,19 @@ +HEADERS = window.h \ + animation.h +SOURCES = main.cpp \ + window.cpp + +FORMS = form.ui + +RESOURCES = easing.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/easing +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS easing.pro images +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/easing +INSTALLS += target sources + +symbian { + TARGET.UID3 = 0xA000E3F6 + include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +} diff --git a/examples/animation/easing/easing.qrc b/examples/animation/easing/easing.qrc new file mode 100644 index 0000000000..7e112d3a9d --- /dev/null +++ b/examples/animation/easing/easing.qrc @@ -0,0 +1,5 @@ +<!DOCTYPE RCC><RCC version="1.0"> + <qresource> + <file>images/qt-logo.png</file> + </qresource> + </RCC>
\ No newline at end of file diff --git a/examples/animation/easing/form.ui b/examples/animation/easing/form.ui new file mode 100644 index 0000000000..b60ade86a4 --- /dev/null +++ b/examples/animation/easing/form.ui @@ -0,0 +1,201 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>545</width> + <height>471</height> + </rect> + </property> + <property name="windowTitle"> + <string>Easing curves</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <widget class="QListWidget" name="easingCurvePicker"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>120</height> + </size> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + <property name="movement"> + <enum>QListView::Static</enum> + </property> + <property name="isWrapping" stdset="0"> + <bool>false</bool> + </property> + <property name="viewMode"> + <enum>QListView::IconMode</enum> + </property> + <property name="selectionRectVisible"> + <bool>false</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Path type</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QRadioButton" name="lineRadio"> + <property name="text"> + <string>Line</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <attribute name="buttonGroup"> + <string>buttonGroup</string> + </attribute> + </widget> + </item> + <item> + <widget class="QRadioButton" name="circleRadio"> + <property name="text"> + <string>Circle</string> + </property> + <attribute name="buttonGroup"> + <string>buttonGroup</string> + </attribute> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Properties</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::AllNonFixedFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Period</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QDoubleSpinBox" name="periodSpinBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <double>-1.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>-1.000000000000000</double> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Amplitude</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QDoubleSpinBox" name="amplitudeSpinBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <double>-1.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>-1.000000000000000</double> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Overshoot</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QDoubleSpinBox" name="overshootSpinBox"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="minimum"> + <double>-1.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.100000000000000</double> + </property> + <property name="value"> + <double>-1.000000000000000</double> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="1"> + <widget class="QGraphicsView" name="graphicsView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> + <buttongroups> + <buttongroup name="buttonGroup"/> + </buttongroups> +</ui> diff --git a/examples/animation/easing/images/qt-logo.png b/examples/animation/easing/images/qt-logo.png Binary files differnew file mode 100644 index 0000000000..14ddf2a028 --- /dev/null +++ b/examples/animation/easing/images/qt-logo.png diff --git a/examples/animation/easing/main.cpp b/examples/animation/easing/main.cpp new file mode 100644 index 0000000000..def1db27de --- /dev/null +++ b/examples/animation/easing/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 <QtGui> +#include "window.h" + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(easing); + QApplication app(argc, argv); + Window w; + w.resize(400, 400); + w.show(); + return app.exec(); +} diff --git a/examples/animation/easing/window.cpp b/examples/animation/easing/window.cpp new file mode 100644 index 0000000000..b466cec3d0 --- /dev/null +++ b/examples/animation/easing/window.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "window.h" + +Window::Window(QWidget *parent) + : QWidget(parent), m_iconSize(64, 64) +{ + m_ui.setupUi(this); + QButtonGroup *buttonGroup = findChild<QButtonGroup *>(); // ### workaround for uic in 4.4 + m_ui.easingCurvePicker->setIconSize(m_iconSize); + m_ui.easingCurvePicker->setMinimumHeight(m_iconSize.height() + 50); + buttonGroup->setId(m_ui.lineRadio, 0); + buttonGroup->setId(m_ui.circleRadio, 1); + + QEasingCurve dummy; + m_ui.periodSpinBox->setValue(dummy.period()); + m_ui.amplitudeSpinBox->setValue(dummy.amplitude()); + m_ui.overshootSpinBox->setValue(dummy.overshoot()); + + connect(m_ui.easingCurvePicker, SIGNAL(currentRowChanged(int)), this, SLOT(curveChanged(int))); + connect(buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(pathChanged(int))); + connect(m_ui.periodSpinBox, SIGNAL(valueChanged(double)), this, SLOT(periodChanged(double))); + connect(m_ui.amplitudeSpinBox, SIGNAL(valueChanged(double)), this, SLOT(amplitudeChanged(double))); + connect(m_ui.overshootSpinBox, SIGNAL(valueChanged(double)), this, SLOT(overshootChanged(double))); + createCurveIcons(); + + QPixmap pix(QLatin1String(":/images/qt-logo.png")); + m_item = new PixmapItem(pix); + m_scene.addItem(m_item); + m_ui.graphicsView->setScene(&m_scene); + + m_anim = new Animation(m_item, "pos"); + m_anim->setEasingCurve(QEasingCurve::OutBounce); + m_ui.easingCurvePicker->setCurrentRow(int(QEasingCurve::OutBounce)); + + startAnimation(); +} + +void Window::createCurveIcons() +{ + QPixmap pix(m_iconSize); + QPainter painter(&pix); + QLinearGradient gradient(0,0, 0, m_iconSize.height()); + gradient.setColorAt(0.0, QColor(240, 240, 240)); + gradient.setColorAt(1.0, QColor(224, 224, 224)); + QBrush brush(gradient); + const QMetaObject &mo = QEasingCurve::staticMetaObject; + QMetaEnum metaEnum = mo.enumerator(mo.indexOfEnumerator("Type")); + // Skip QEasingCurve::Custom + for (int i = 0; i < QEasingCurve::NCurveTypes - 1; ++i) { + painter.fillRect(QRect(QPoint(0, 0), m_iconSize), brush); + QEasingCurve curve((QEasingCurve::Type)i); + painter.setPen(QColor(0, 0, 255, 64)); + qreal xAxis = m_iconSize.height()/1.5; + qreal yAxis = m_iconSize.width()/3; + painter.drawLine(0, xAxis, m_iconSize.width(), xAxis); + painter.drawLine(yAxis, 0, yAxis, m_iconSize.height()); + + qreal curveScale = m_iconSize.height()/2; + + painter.setPen(Qt::NoPen); + + // start point + painter.setBrush(Qt::red); + QPoint start(yAxis, xAxis - curveScale * curve.valueForProgress(0)); + painter.drawRect(start.x() - 1, start.y() - 1, 3, 3); + + // end point + painter.setBrush(Qt::blue); + QPoint end(yAxis + curveScale, xAxis - curveScale * curve.valueForProgress(1)); + painter.drawRect(end.x() - 1, end.y() - 1, 3, 3); + + QPainterPath curvePath; + curvePath.moveTo(start); + for (qreal t = 0; t <= 1.0; t+=1.0/curveScale) { + QPoint to; + to.setX(yAxis + curveScale * t); + to.setY(xAxis - curveScale * curve.valueForProgress(t)); + curvePath.lineTo(to); + } + painter.setRenderHint(QPainter::Antialiasing, true); + painter.strokePath(curvePath, QColor(32, 32, 32)); + painter.setRenderHint(QPainter::Antialiasing, false); + QListWidgetItem *item = new QListWidgetItem; + item->setIcon(QIcon(pix)); + item->setText(metaEnum.key(i)); + m_ui.easingCurvePicker->addItem(item); + } +} + +void Window::startAnimation() +{ + m_anim->setStartValue(QPointF(0, 0)); + m_anim->setEndValue(QPointF(100, 100)); + m_anim->setDuration(2000); + m_anim->setLoopCount(-1); // forever + m_anim->start(); +} + +void Window::curveChanged(int row) +{ + QEasingCurve::Type curveType = (QEasingCurve::Type)row; + m_anim->setEasingCurve(curveType); + m_anim->setCurrentTime(0); + + bool isElastic = curveType >= QEasingCurve::InElastic && curveType <= QEasingCurve::OutInElastic; + bool isBounce = curveType >= QEasingCurve::InBounce && curveType <= QEasingCurve::OutInBounce; + m_ui.periodSpinBox->setEnabled(isElastic); + m_ui.amplitudeSpinBox->setEnabled(isElastic || isBounce); + m_ui.overshootSpinBox->setEnabled(curveType >= QEasingCurve::InBack && curveType <= QEasingCurve::OutInBack); +} + +void Window::pathChanged(int index) +{ + m_anim->setPathType((Animation::PathType)index); +} + +void Window::periodChanged(double value) +{ + QEasingCurve curve = m_anim->easingCurve(); + curve.setPeriod(value); + m_anim->setEasingCurve(curve); +} + +void Window::amplitudeChanged(double value) +{ + QEasingCurve curve = m_anim->easingCurve(); + curve.setAmplitude(value); + m_anim->setEasingCurve(curve); +} + +void Window::overshootChanged(double value) +{ + QEasingCurve curve = m_anim->easingCurve(); + curve.setOvershoot(value); + m_anim->setEasingCurve(curve); +} + diff --git a/examples/animation/easing/window.h b/examples/animation/easing/window.h new file mode 100644 index 0000000000..bbdf14e0dc --- /dev/null +++ b/examples/animation/easing/window.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 <QtGui> + +#include "ui_form.h" +#include "animation.h" + +class PixmapItem : public QObject, public QGraphicsPixmapItem +{ + Q_OBJECT + Q_PROPERTY(QPointF pos READ pos WRITE setPos) +public: + PixmapItem(const QPixmap &pix) : QGraphicsPixmapItem(pix) + { + } +}; + +class Window : public QWidget { + Q_OBJECT +public: + Window(QWidget *parent = 0); +private slots: + void curveChanged(int row); + void pathChanged(int index); + void periodChanged(double); + void amplitudeChanged(double); + void overshootChanged(double); + +private: + void createCurveIcons(); + void startAnimation(); + + Ui::Form m_ui; + QGraphicsScene m_scene; + PixmapItem *m_item; + Animation *m_anim; + QSize m_iconSize; + + +}; diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp new file mode 100644 index 0000000000..3194c1b623 --- /dev/null +++ b/examples/animation/moveblocks/main.cpp @@ -0,0 +1,319 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 <QtCore> +#include <QtGui> + +//![15] +class StateSwitchEvent: public QEvent +{ +public: + StateSwitchEvent() + : QEvent(Type(StateSwitchType)) + { + } + + StateSwitchEvent(int rand) + : QEvent(Type(StateSwitchType)), + m_rand(rand) + { + } + + enum { StateSwitchType = QEvent::User + 256 }; + + int rand() const { return m_rand; } + +private: + int m_rand; +}; +//![15] + +//![16] +class QGraphicsRectWidget : public QGraphicsWidget +{ +public: + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, + QWidget *) + { + painter->fillRect(rect(), Qt::blue); + } +}; +//![16] + +class StateSwitchTransition: public QAbstractTransition +{ +public: + StateSwitchTransition(int rand) + : QAbstractTransition(), + m_rand(rand) + { + } + +protected: +//![14] + virtual bool eventTest(QEvent *event) + { + return (event->type() == QEvent::Type(StateSwitchEvent::StateSwitchType)) + && (static_cast<StateSwitchEvent *>(event)->rand() == m_rand); + } +//![14] + + virtual void onTransition(QEvent *) {} + +private: + int m_rand; +}; + +//![10] +class StateSwitcher : public QState +{ + Q_OBJECT +public: + StateSwitcher(QStateMachine *machine) + : QState(machine), m_stateCount(0), m_lastIndex(0) + { } +//![10] + +//![11] + virtual void onEntry(QEvent *) + { + int n; + while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex) + { } + m_lastIndex = n; + machine()->postEvent(new StateSwitchEvent(n)); + } + virtual void onExit(QEvent *) {} +//![11] + +//![12] + void addState(QState *state, QAbstractAnimation *animation) { + StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount); + trans->setTargetState(state); + addTransition(trans); + trans->addAnimation(animation); + } +//![12] + +private: + int m_stateCount; + int m_lastIndex; +}; + +//![13] +QState *createGeometryState(QObject *w1, const QRect &rect1, + QObject *w2, const QRect &rect2, + QObject *w3, const QRect &rect3, + QObject *w4, const QRect &rect4, + QState *parent) +{ + QState *result = new QState(parent); + result->assignProperty(w1, "geometry", rect1); + result->assignProperty(w2, "geometry", rect2); + result->assignProperty(w3, "geometry", rect3); + result->assignProperty(w4, "geometry", rect4); + + return result; +} +//![13] + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + +#if 0 + QWidget window; + QPalette palette; + palette.setBrush(QPalette::Window, Qt::black); + window.setPalette(palette); + QPushButton *button1 = new QPushButton("A", &window); + QPushButton *button2 = new QPushButton("B", &window); + QPushButton *button3 = new QPushButton("C", &window); + QPushButton *button4 = new QPushButton("D", &window); + + button1->setObjectName("button1"); + button2->setObjectName("button2"); + button3->setObjectName("button3"); + button4->setObjectName("button4"); +#else +//![1] + QGraphicsRectWidget *button1 = new QGraphicsRectWidget; + QGraphicsRectWidget *button2 = new QGraphicsRectWidget; + QGraphicsRectWidget *button3 = new QGraphicsRectWidget; + QGraphicsRectWidget *button4 = new QGraphicsRectWidget; + button2->setZValue(1); + button3->setZValue(2); + button4->setZValue(3); + QGraphicsScene scene(0, 0, 300, 300); + scene.setBackgroundBrush(Qt::black); + scene.addItem(button1); + scene.addItem(button2); + scene.addItem(button3); + scene.addItem(button4); +//![1] + QGraphicsView window(&scene); + window.setFrameStyle(0); + window.setAlignment(Qt::AlignLeft | Qt::AlignTop); + window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); +#endif +//![2] + QStateMachine machine; + + QState *group = new QState(); + group->setObjectName("group"); + QTimer timer; + timer.setInterval(1250); + timer.setSingleShot(true); + QObject::connect(group, SIGNAL(entered()), &timer, SLOT(start())); +//![2] + +//![3] + QState *state1; + QState *state2; + QState *state3; + QState *state4; + QState *state5; + QState *state6; + QState *state7; + + state1 = createGeometryState(button1, QRect(100, 0, 50, 50), + button2, QRect(150, 0, 50, 50), + button3, QRect(200, 0, 50, 50), + button4, QRect(250, 0, 50, 50), + group); +//![3] + state2 = createGeometryState(button1, QRect(250, 100, 50, 50), + button2, QRect(250, 150, 50, 50), + button3, QRect(250, 200, 50, 50), + button4, QRect(250, 250, 50, 50), + group); + state3 = createGeometryState(button1, QRect(150, 250, 50, 50), + button2, QRect(100, 250, 50, 50), + button3, QRect(50, 250, 50, 50), + button4, QRect(0, 250, 50, 50), + group); + state4 = createGeometryState(button1, QRect(0, 150, 50, 50), + button2, QRect(0, 100, 50, 50), + button3, QRect(0, 50, 50, 50), + button4, QRect(0, 0, 50, 50), + group); + state5 = createGeometryState(button1, QRect(100, 100, 50, 50), + button2, QRect(150, 100, 50, 50), + button3, QRect(100, 150, 50, 50), + button4, QRect(150, 150, 50, 50), + group); + state6 = createGeometryState(button1, QRect(50, 50, 50, 50), + button2, QRect(200, 50, 50, 50), + button3, QRect(50, 200, 50, 50), + button4, QRect(200, 200, 50, 50), + group); +//![4] + state7 = createGeometryState(button1, QRect(0, 0, 50, 50), + button2, QRect(250, 0, 50, 50), + button3, QRect(0, 250, 50, 50), + button4, QRect(250, 250, 50, 50), + group); + group->setInitialState(state1); +//![4] + +//![5] + QParallelAnimationGroup animationGroup; + QSequentialAnimationGroup *subGroup; + + QPropertyAnimation *anim = new QPropertyAnimation(button4, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + animationGroup.addAnimation(anim); +//![5] + +//![6] + subGroup = new QSequentialAnimationGroup(&animationGroup); + subGroup->addPause(100); + anim = new QPropertyAnimation(button3, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + subGroup->addAnimation(anim); +//![6] + + subGroup = new QSequentialAnimationGroup(&animationGroup); + subGroup->addPause(150); + anim = new QPropertyAnimation(button2, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + subGroup->addAnimation(anim); + + subGroup = new QSequentialAnimationGroup(&animationGroup); + subGroup->addPause(200); + anim = new QPropertyAnimation(button1, "geometry"); + anim->setDuration(1000); + anim->setEasingCurve(QEasingCurve::OutElastic); + subGroup->addAnimation(anim); + +//![7] + StateSwitcher *stateSwitcher = new StateSwitcher(&machine); + stateSwitcher->setObjectName("stateSwitcher"); + group->addTransition(&timer, SIGNAL(timeout()), stateSwitcher); + stateSwitcher->addState(state1, &animationGroup); + stateSwitcher->addState(state2, &animationGroup); +//![7] + stateSwitcher->addState(state3, &animationGroup); + stateSwitcher->addState(state4, &animationGroup); + stateSwitcher->addState(state5, &animationGroup); + stateSwitcher->addState(state6, &animationGroup); +//![8] + stateSwitcher->addState(state7, &animationGroup); +//![8] + +//![9] + machine.addState(group); + machine.setInitialState(group); + machine.start(); +//![9] + + window.resize(300, 300); + window.show(); + + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/animation/moveblocks/moveblocks.pro b/examples/animation/moveblocks/moveblocks.pro new file mode 100644 index 0000000000..6451b67886 --- /dev/null +++ b/examples/animation/moveblocks/moveblocks.pro @@ -0,0 +1,12 @@ +SOURCES = main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/moveblocks +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS moveblocks.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/moveblocks +INSTALLS += target sources + +symbian { + TARGET.UID3 = 0xA000E3F7 + include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +} diff --git a/examples/animation/states/accessories-dictionary.png b/examples/animation/states/accessories-dictionary.png Binary files differnew file mode 100644 index 0000000000..e9bd55d918 --- /dev/null +++ b/examples/animation/states/accessories-dictionary.png diff --git a/examples/animation/states/akregator.png b/examples/animation/states/akregator.png Binary files differnew file mode 100644 index 0000000000..a086f45ab6 --- /dev/null +++ b/examples/animation/states/akregator.png diff --git a/examples/animation/states/digikam.png b/examples/animation/states/digikam.png Binary files differnew file mode 100644 index 0000000000..9de9fb2f80 --- /dev/null +++ b/examples/animation/states/digikam.png diff --git a/examples/animation/states/help-browser.png b/examples/animation/states/help-browser.png Binary files differnew file mode 100644 index 0000000000..db92faa4e7 --- /dev/null +++ b/examples/animation/states/help-browser.png diff --git a/examples/animation/states/k3b.png b/examples/animation/states/k3b.png Binary files differnew file mode 100644 index 0000000000..bbcafcfba1 --- /dev/null +++ b/examples/animation/states/k3b.png diff --git a/examples/animation/states/kchart.png b/examples/animation/states/kchart.png Binary files differnew file mode 100644 index 0000000000..1dd115be87 --- /dev/null +++ b/examples/animation/states/kchart.png diff --git a/examples/animation/states/main.cpp b/examples/animation/states/main.cpp new file mode 100644 index 0000000000..1565489069 --- /dev/null +++ b/examples/animation/states/main.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 <QtGui> + +class Pixmap : public QGraphicsObject +{ + Q_OBJECT +public: + Pixmap(const QPixmap &pix) : QGraphicsObject(), p(pix) + { + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + { + painter->drawPixmap(QPointF(), p); + } + + QRectF boundingRect() const + { + return QRectF( QPointF(0, 0), p.size()); + } + +private: + QPixmap p; +}; + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(states); + + QApplication app(argc, argv); + + // Text edit and button + QTextEdit *edit = new QTextEdit; + edit->setText("asdf lkjha yuoiqwe asd iuaysd u iasyd uiy " + "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy " + "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy " + "asdf lkjha yuoiqwe asd iuaysd u iasyd uiy!"); + + QPushButton *button = new QPushButton; + QGraphicsProxyWidget *buttonProxy = new QGraphicsProxyWidget; + buttonProxy->setWidget(button); + QGraphicsProxyWidget *editProxy = new QGraphicsProxyWidget; + editProxy->setWidget(edit); + + QGroupBox *box = new QGroupBox; + box->setFlat(true); + box->setTitle("Options"); + + QVBoxLayout *layout2 = new QVBoxLayout; + box->setLayout(layout2); + layout2->addWidget(new QRadioButton("Herring")); + layout2->addWidget(new QRadioButton("Blue Parrot")); + layout2->addWidget(new QRadioButton("Petunias")); + layout2->addStretch(); + + QGraphicsProxyWidget *boxProxy = new QGraphicsProxyWidget; + boxProxy->setWidget(box); + + // Parent widget + QGraphicsWidget *widget = new QGraphicsWidget; + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, widget); + layout->addItem(editProxy); + layout->addItem(buttonProxy); + widget->setLayout(layout); + + Pixmap *p1 = new Pixmap(QPixmap(":/digikam.png")); + Pixmap *p2 = new Pixmap(QPixmap(":/akregator.png")); + Pixmap *p3 = new Pixmap(QPixmap(":/accessories-dictionary.png")); + Pixmap *p4 = new Pixmap(QPixmap(":/k3b.png")); + Pixmap *p5 = new Pixmap(QPixmap(":/help-browser.png")); + Pixmap *p6 = new Pixmap(QPixmap(":/kchart.png")); + + QGraphicsScene scene(0, 0, 400, 300); + scene.setBackgroundBrush(scene.palette().window()); + scene.addItem(widget); + scene.addItem(boxProxy); + scene.addItem(p1); + scene.addItem(p2); + scene.addItem(p3); + scene.addItem(p4); + scene.addItem(p5); + scene.addItem(p6); + + QStateMachine machine; + QState *state1 = new QState(&machine); + QState *state2 = new QState(&machine); + QState *state3 = new QState(&machine); + machine.setInitialState(state1); + + // State 1 + state1->assignProperty(button, "text", "Switch to state 2"); + state1->assignProperty(widget, "geometry", QRectF(0, 0, 400, 150)); + state1->assignProperty(box, "geometry", QRect(-200, 150, 200, 150)); + state1->assignProperty(p1, "pos", QPointF(68, 185)); + state1->assignProperty(p2, "pos", QPointF(168, 185)); + state1->assignProperty(p3, "pos", QPointF(268, 185)); + state1->assignProperty(p4, "pos", QPointF(68-150, 48-150)); + state1->assignProperty(p5, "pos", QPointF(168, 48-150)); + state1->assignProperty(p6, "pos", QPointF(268+150, 48-150)); + state1->assignProperty(p1, "rotation", qreal(0)); + state1->assignProperty(p2, "rotation", qreal(0)); + state1->assignProperty(p3, "rotation", qreal(0)); + state1->assignProperty(p4, "rotation", qreal(-270)); + state1->assignProperty(p5, "rotation", qreal(-90)); + state1->assignProperty(p6, "rotation", qreal(270)); + state1->assignProperty(boxProxy, "opacity", qreal(0)); + state1->assignProperty(p1, "opacity", qreal(1)); + state1->assignProperty(p2, "opacity", qreal(1)); + state1->assignProperty(p3, "opacity", qreal(1)); + state1->assignProperty(p4, "opacity", qreal(0)); + state1->assignProperty(p5, "opacity", qreal(0)); + state1->assignProperty(p6, "opacity", qreal(0)); + + // State 2 + state2->assignProperty(button, "text", "Switch to state 3"); + state2->assignProperty(widget, "geometry", QRectF(200, 150, 200, 150)); + state2->assignProperty(box, "geometry", QRect(9, 150, 190, 150)); + state2->assignProperty(p1, "pos", QPointF(68-150, 185+150)); + state2->assignProperty(p2, "pos", QPointF(168, 185+150)); + state2->assignProperty(p3, "pos", QPointF(268+150, 185+150)); + state2->assignProperty(p4, "pos", QPointF(64, 48)); + state2->assignProperty(p5, "pos", QPointF(168, 48)); + state2->assignProperty(p6, "pos", QPointF(268, 48)); + state2->assignProperty(p1, "rotation", qreal(-270)); + state2->assignProperty(p2, "rotation", qreal(90)); + state2->assignProperty(p3, "rotation", qreal(270)); + state2->assignProperty(p4, "rotation", qreal(0)); + state2->assignProperty(p5, "rotation", qreal(0)); + state2->assignProperty(p6, "rotation", qreal(0)); + state2->assignProperty(boxProxy, "opacity", qreal(1)); + state2->assignProperty(p1, "opacity", qreal(0)); + state2->assignProperty(p2, "opacity", qreal(0)); + state2->assignProperty(p3, "opacity", qreal(0)); + state2->assignProperty(p4, "opacity", qreal(1)); + state2->assignProperty(p5, "opacity", qreal(1)); + state2->assignProperty(p6, "opacity", qreal(1)); + + // State 3 + state3->assignProperty(button, "text", "Switch to state 1"); + state3->assignProperty(p1, "pos", QPointF(0, 5)); + state3->assignProperty(p2, "pos", QPointF(0, 5 + 64 + 5)); + state3->assignProperty(p3, "pos", QPointF(5, 5 + (64 + 5) + 64)); + state3->assignProperty(p4, "pos", QPointF(5 + 64 + 5, 5)); + state3->assignProperty(p5, "pos", QPointF(5 + 64 + 5, 5 + 64 + 5)); + state3->assignProperty(p6, "pos", QPointF(5 + 64 + 5, 5 + (64 + 5) + 64)); + state3->assignProperty(widget, "geometry", QRectF(138, 5, 400 - 138, 200)); + state3->assignProperty(box, "geometry", QRect(5, 205, 400, 90)); + state3->assignProperty(p1, "opacity", qreal(1)); + state3->assignProperty(p2, "opacity", qreal(1)); + state3->assignProperty(p3, "opacity", qreal(1)); + state3->assignProperty(p4, "opacity", qreal(1)); + state3->assignProperty(p5, "opacity", qreal(1)); + state3->assignProperty(p6, "opacity", qreal(1)); + + QAbstractTransition *t1 = state1->addTransition(button, SIGNAL(clicked()), state2); + QSequentialAnimationGroup *animation1SubGroup = new QSequentialAnimationGroup; + animation1SubGroup->addPause(250); + animation1SubGroup->addAnimation(new QPropertyAnimation(box, "geometry")); + t1->addAnimation(animation1SubGroup); + t1->addAnimation(new QPropertyAnimation(widget, "geometry")); + t1->addAnimation(new QPropertyAnimation(p1, "pos")); + t1->addAnimation(new QPropertyAnimation(p2, "pos")); + t1->addAnimation(new QPropertyAnimation(p3, "pos")); + t1->addAnimation(new QPropertyAnimation(p4, "pos")); + t1->addAnimation(new QPropertyAnimation(p5, "pos")); + t1->addAnimation(new QPropertyAnimation(p6, "pos")); + t1->addAnimation(new QPropertyAnimation(p1, "rotation")); + t1->addAnimation(new QPropertyAnimation(p2, "rotation")); + t1->addAnimation(new QPropertyAnimation(p3, "rotation")); + t1->addAnimation(new QPropertyAnimation(p4, "rotation")); + t1->addAnimation(new QPropertyAnimation(p5, "rotation")); + t1->addAnimation(new QPropertyAnimation(p6, "rotation")); + t1->addAnimation(new QPropertyAnimation(p1, "opacity")); + t1->addAnimation(new QPropertyAnimation(p2, "opacity")); + t1->addAnimation(new QPropertyAnimation(p3, "opacity")); + t1->addAnimation(new QPropertyAnimation(p4, "opacity")); + t1->addAnimation(new QPropertyAnimation(p5, "opacity")); + t1->addAnimation(new QPropertyAnimation(p6, "opacity")); + + QAbstractTransition *t2 = state2->addTransition(button, SIGNAL(clicked()), state3); + t2->addAnimation(new QPropertyAnimation(box, "geometry")); + t2->addAnimation(new QPropertyAnimation(widget, "geometry")); + t2->addAnimation(new QPropertyAnimation(p1, "pos")); + t2->addAnimation(new QPropertyAnimation(p2, "pos")); + t2->addAnimation(new QPropertyAnimation(p3, "pos")); + t2->addAnimation(new QPropertyAnimation(p4, "pos")); + t2->addAnimation(new QPropertyAnimation(p5, "pos")); + t2->addAnimation(new QPropertyAnimation(p6, "pos")); + t2->addAnimation(new QPropertyAnimation(p1, "rotation")); + t2->addAnimation(new QPropertyAnimation(p2, "rotation")); + t2->addAnimation(new QPropertyAnimation(p3, "rotation")); + t2->addAnimation(new QPropertyAnimation(p4, "rotation")); + t2->addAnimation(new QPropertyAnimation(p5, "rotation")); + t2->addAnimation(new QPropertyAnimation(p6, "rotation")); + t2->addAnimation(new QPropertyAnimation(p1, "opacity")); + t2->addAnimation(new QPropertyAnimation(p2, "opacity")); + t2->addAnimation(new QPropertyAnimation(p3, "opacity")); + t2->addAnimation(new QPropertyAnimation(p4, "opacity")); + t2->addAnimation(new QPropertyAnimation(p5, "opacity")); + t2->addAnimation(new QPropertyAnimation(p6, "opacity")); + + QAbstractTransition *t3 = state3->addTransition(button, SIGNAL(clicked()), state1); + t3->addAnimation(new QPropertyAnimation(box, "geometry")); + t3->addAnimation(new QPropertyAnimation(widget, "geometry")); + t3->addAnimation(new QPropertyAnimation(p1, "pos")); + t3->addAnimation(new QPropertyAnimation(p2, "pos")); + t3->addAnimation(new QPropertyAnimation(p3, "pos")); + t3->addAnimation(new QPropertyAnimation(p4, "pos")); + t3->addAnimation(new QPropertyAnimation(p5, "pos")); + t3->addAnimation(new QPropertyAnimation(p6, "pos")); + t3->addAnimation(new QPropertyAnimation(p1, "rotation")); + t3->addAnimation(new QPropertyAnimation(p2, "rotation")); + t3->addAnimation(new QPropertyAnimation(p3, "rotation")); + t3->addAnimation(new QPropertyAnimation(p4, "rotation")); + t3->addAnimation(new QPropertyAnimation(p5, "rotation")); + t3->addAnimation(new QPropertyAnimation(p6, "rotation")); + t3->addAnimation(new QPropertyAnimation(p1, "opacity")); + t3->addAnimation(new QPropertyAnimation(p2, "opacity")); + t3->addAnimation(new QPropertyAnimation(p3, "opacity")); + t3->addAnimation(new QPropertyAnimation(p4, "opacity")); + t3->addAnimation(new QPropertyAnimation(p5, "opacity")); + t3->addAnimation(new QPropertyAnimation(p6, "opacity")); + + machine.start(); + + QGraphicsView view(&scene); + view.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/animation/states/states.pro b/examples/animation/states/states.pro new file mode 100644 index 0000000000..dd5e09f365 --- /dev/null +++ b/examples/animation/states/states.pro @@ -0,0 +1,13 @@ +SOURCES += main.cpp +RESOURCES += states.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/states +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS states.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/states +INSTALLS += target sources + +symbian { + TARGET.UID3 = 0xA000E3F8 + include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +} diff --git a/examples/animation/states/states.qrc b/examples/animation/states/states.qrc new file mode 100644 index 0000000000..60ab3f7a60 --- /dev/null +++ b/examples/animation/states/states.qrc @@ -0,0 +1,10 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>accessories-dictionary.png</file> + <file>akregator.png</file> + <file>digikam.png</file> + <file>help-browser.png</file> + <file>k3b.png</file> + <file>kchart.png</file> +</qresource> +</RCC> diff --git a/examples/animation/stickman/animation.cpp b/examples/animation/stickman/animation.cpp new file mode 100644 index 0000000000..af7144be2c --- /dev/null +++ b/examples/animation/stickman/animation.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "animation.h" + +#include <QPointF> +#include <QIODevice> +#include <QDataStream> + +class Frame +{ +public: + Frame() { + } + + int nodeCount() const + { + return m_nodePositions.size(); + } + + void setNodeCount(int nodeCount) + { + while (nodeCount > m_nodePositions.size()) + m_nodePositions.append(QPointF()); + + while (nodeCount < m_nodePositions.size()) + m_nodePositions.removeLast(); + } + + QPointF nodePos(int idx) const + { + return m_nodePositions.at(idx); + } + + void setNodePos(int idx, const QPointF &pos) + { + m_nodePositions[idx] = pos; + } + +private: + QList<QPointF> m_nodePositions; +}; + +Animation::Animation() +{ + m_currentFrame = 0; + m_frames.append(new Frame); +} + +Animation::~Animation() +{ + qDeleteAll(m_frames); +} + +void Animation::setTotalFrames(int totalFrames) +{ + while (m_frames.size() < totalFrames) + m_frames.append(new Frame); + + while (totalFrames < m_frames.size()) + delete m_frames.takeLast(); +} + +int Animation::totalFrames() const +{ + return m_frames.size(); +} + +void Animation::setCurrentFrame(int currentFrame) +{ + m_currentFrame = qMax(qMin(currentFrame, totalFrames()-1), 0); +} + +int Animation::currentFrame() const +{ + return m_currentFrame; +} + +void Animation::setNodeCount(int nodeCount) +{ + Frame *frame = m_frames.at(m_currentFrame); + frame->setNodeCount(nodeCount); +} + +int Animation::nodeCount() const +{ + Frame *frame = m_frames.at(m_currentFrame); + return frame->nodeCount(); +} + +void Animation::setNodePos(int idx, const QPointF &pos) +{ + Frame *frame = m_frames.at(m_currentFrame); + frame->setNodePos(idx, pos); +} + +QPointF Animation::nodePos(int idx) const +{ + Frame *frame = m_frames.at(m_currentFrame); + return frame->nodePos(idx); +} + +QString Animation::name() const +{ + return m_name; +} + +void Animation::setName(const QString &name) +{ + m_name = name; +} + +void Animation::save(QIODevice *device) const +{ + QDataStream stream(device); + stream << m_name; + stream << m_frames.size(); + foreach (Frame *frame, m_frames) { + stream << frame->nodeCount(); + for (int i=0; i<frame->nodeCount(); ++i) + stream << frame->nodePos(i); + } +} + +void Animation::load(QIODevice *device) +{ + if (!m_frames.isEmpty()) + qDeleteAll(m_frames); + + m_frames.clear(); + + QDataStream stream(device); + stream >> m_name; + + int frameCount; + stream >> frameCount; + + for (int i=0; i<frameCount; ++i) { + + int nodeCount; + stream >> nodeCount; + + Frame *frame = new Frame; + frame->setNodeCount(nodeCount); + + for (int j=0; j<nodeCount; ++j) { + QPointF pos; + stream >> pos; + + frame->setNodePos(j, pos); + } + + m_frames.append(frame); + } +} diff --git a/examples/animation/stickman/animation.h b/examples/animation/stickman/animation.h new file mode 100644 index 0000000000..51edda6e63 --- /dev/null +++ b/examples/animation/stickman/animation.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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$ +** +****************************************************************************/ + +#ifndef ANIMATION_H +#define ANIMATION_H + +#include <QPointF> +#include <QList> +#include <QString> + +class Frame; +QT_BEGIN_NAMESPACE +class QIODevice; +QT_END_NAMESPACE +class Animation +{ +public: + Animation(); + ~Animation(); + + void setTotalFrames(int totalFrames); + int totalFrames() const; + + void setCurrentFrame(int currentFrame); + int currentFrame() const; + + void setNodeCount(int nodeCount); + int nodeCount() const; + + void setNodePos(int idx, const QPointF &pos); + QPointF nodePos(int idx) const; + + QString name() const; + void setName(const QString &name); + + void save(QIODevice *device) const; + void load(QIODevice *device); + +private: + QString m_name; + QList<Frame *> m_frames; + int m_currentFrame; +}; + +#endif diff --git a/examples/animation/stickman/animations/chilling b/examples/animation/stickman/animations/chilling Binary files differnew file mode 100644 index 0000000000..a81fc7a18c --- /dev/null +++ b/examples/animation/stickman/animations/chilling diff --git a/examples/animation/stickman/animations/dancing b/examples/animation/stickman/animations/dancing Binary files differnew file mode 100644 index 0000000000..462f66f89b --- /dev/null +++ b/examples/animation/stickman/animations/dancing diff --git a/examples/animation/stickman/animations/dead b/examples/animation/stickman/animations/dead Binary files differnew file mode 100644 index 0000000000..9859b4b4cd --- /dev/null +++ b/examples/animation/stickman/animations/dead diff --git a/examples/animation/stickman/animations/jumping b/examples/animation/stickman/animations/jumping Binary files differnew file mode 100644 index 0000000000..12661a15f8 --- /dev/null +++ b/examples/animation/stickman/animations/jumping diff --git a/examples/animation/stickman/graphicsview.cpp b/examples/animation/stickman/graphicsview.cpp new file mode 100644 index 0000000000..23036efe92 --- /dev/null +++ b/examples/animation/stickman/graphicsview.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "graphicsview.h" +#include "stickman.h" + +#include <QtGui/QKeyEvent> +#include <QtGui/QGraphicsScene> +#include <QtGui/QGraphicsView> + +GraphicsView::GraphicsView(QWidget *parent) : QGraphicsView(parent), m_editor(0) {} + +void GraphicsView::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Escape) + close(); + emit keyPressed(Qt::Key(e->key())); +} + + diff --git a/examples/animation/stickman/graphicsview.h b/examples/animation/stickman/graphicsview.h new file mode 100644 index 0000000000..9cf87b63e6 --- /dev/null +++ b/examples/animation/stickman/graphicsview.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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$ +** +****************************************************************************/ + +#ifndef GRAPHICSVIEW_H +#define GRAPHICSVIEW + +#include <QtGui/QGraphicsView> + +class MainWindow; +class GraphicsView: public QGraphicsView +{ + Q_OBJECT +public: + GraphicsView(QWidget *parent = 0); + +protected: + void keyPressEvent(QKeyEvent *); + +signals: + void keyPressed(int key); + +private: + MainWindow *m_editor; +}; + +#endif diff --git a/examples/animation/stickman/lifecycle.cpp b/examples/animation/stickman/lifecycle.cpp new file mode 100644 index 0000000000..4abcdc22e5 --- /dev/null +++ b/examples/animation/stickman/lifecycle.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "lifecycle.h" +#include "stickman.h" +#include "node.h" +#include "animation.h" +#include "graphicsview.h" + +#include <QtCore> +#include <QtGui> + +class KeyPressTransition: public QSignalTransition +{ +public: + KeyPressTransition(GraphicsView *receiver, Qt::Key key) + : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key) + { + } + KeyPressTransition(GraphicsView *receiver, Qt::Key key, QAbstractState *target) + : QSignalTransition(receiver, SIGNAL(keyPressed(int))), m_key(key) + { + setTargetState(target); + } + + virtual bool eventTest(QEvent *e) + { + if (QSignalTransition::eventTest(e)) { + QVariant key = static_cast<QStateMachine::SignalEvent*>(e)->arguments().at(0); + return (key.toInt() == int(m_key)); + } + + return false; + } +private: + Qt::Key m_key; +}; + +//! [4] +class LightningStrikesTransition: public QEventTransition +{ +public: + LightningStrikesTransition(QAbstractState *target) + : QEventTransition(this, QEvent::Timer) + { + setTargetState(target); + qsrand((uint)QDateTime::currentDateTime().toTime_t()); + startTimer(1000); + } + + virtual bool eventTest(QEvent *e) + { + return QEventTransition::eventTest(e) && ((qrand() % 50) == 0); + } +}; +//! [4] + +LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) + : m_stickMan(stickMan), m_keyReceiver(keyReceiver) +{ + // Create animation group to be used for all transitions + m_animationGroup = new QParallelAnimationGroup(); + const int stickManNodeCount = m_stickMan->nodeCount(); + for (int i=0; i<stickManNodeCount; ++i) { + QPropertyAnimation *pa = new QPropertyAnimation(m_stickMan->node(i), "pos"); + m_animationGroup->addAnimation(pa); + } + + // Set up initial state graph +//! [3] + m_machine = new QStateMachine(); + m_machine->addDefaultAnimation(m_animationGroup); +//! [3] + + m_alive = new QState(m_machine); + m_alive->setObjectName("alive"); + + // Make it blink when lightning strikes before entering dead animation + QState *lightningBlink = new QState(m_machine); + lightningBlink->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::white); + lightningBlink->assignProperty(m_stickMan, "penColor", Qt::black); + lightningBlink->assignProperty(m_stickMan, "fillColor", Qt::white); + lightningBlink->assignProperty(m_stickMan, "isDead", true); + +//! [5] + QTimer *timer = new QTimer(lightningBlink); + timer->setSingleShot(true); + timer->setInterval(100); + QObject::connect(lightningBlink, SIGNAL(entered()), timer, SLOT(start())); + QObject::connect(lightningBlink, SIGNAL(exited()), timer, SLOT(stop())); +//! [5] + + m_dead = new QState(m_machine); + m_dead->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::black); + m_dead->assignProperty(m_stickMan, "penColor", Qt::white); + m_dead->assignProperty(m_stickMan, "fillColor", Qt::black); + m_dead->setObjectName("dead"); + + // Idle state (sets no properties) + m_idle = new QState(m_alive); + m_idle->setObjectName("idle"); + + m_alive->setInitialState(m_idle); + + // Lightning strikes at random + m_alive->addTransition(new LightningStrikesTransition(lightningBlink)); +//! [0] + lightningBlink->addTransition(timer, SIGNAL(timeout()), m_dead); +//! [0] + + m_machine->setInitialState(m_alive); +} + +void LifeCycle::setDeathAnimation(const QString &fileName) +{ + QState *deathAnimation = makeState(m_dead, fileName); + m_dead->setInitialState(deathAnimation); +} + +void LifeCycle::start() +{ + m_machine->start(); +} + +void LifeCycle::addActivity(const QString &fileName, Qt::Key key) +{ + QState *state = makeState(m_alive, fileName); + m_alive->addTransition(new KeyPressTransition(m_keyReceiver, key, state)); +} + +QState *LifeCycle::makeState(QState *parentState, const QString &animationFileName) +{ + QState *topLevel = new QState(parentState); + + Animation animation; + { + QFile file(animationFileName); + if (file.open(QIODevice::ReadOnly)) + animation.load(&file); + } + + const int frameCount = animation.totalFrames(); + QState *previousState = 0; + for (int i=0; i<frameCount; ++i) { + animation.setCurrentFrame(i); + +//! [1] + QState *frameState = new QState(topLevel); + const int nodeCount = animation.nodeCount(); + for (int j=0; j<nodeCount; ++j) + frameState->assignProperty(m_stickMan->node(j), "pos", animation.nodePos(j)); +//! [1] + + frameState->setObjectName(QString::fromLatin1("frame %0").arg(i)); + if (previousState == 0) + topLevel->setInitialState(frameState); + else +//! [2] + previousState->addTransition(previousState, SIGNAL(propertiesAssigned()), frameState); +//! [2] + + previousState = frameState; + } + + // Loop + previousState->addTransition(previousState, SIGNAL(propertiesAssigned()), topLevel->initialState()); + + return topLevel; + +} + +LifeCycle::~LifeCycle() +{ + delete m_machine; + delete m_animationGroup; +} diff --git a/examples/animation/stickman/lifecycle.h b/examples/animation/stickman/lifecycle.h new file mode 100644 index 0000000000..1bf3661f6c --- /dev/null +++ b/examples/animation/stickman/lifecycle.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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$ +** +****************************************************************************/ + +#ifndef LIFECYCLE_H +#define LIFECYCLE_H + +#include <Qt> + +class StickMan; +QT_BEGIN_NAMESPACE +class QStateMachine; +class QAnimationGroup; +class QState; +class QAbstractState; +class QAbstractTransition; +QT_END_NAMESPACE +class GraphicsView; +class LifeCycle +{ +public: + LifeCycle(StickMan *stickMan, GraphicsView *keyEventReceiver); + ~LifeCycle(); + + void setDeathAnimation(const QString &fileName); + void addActivity(const QString &fileName, Qt::Key key); + + void start(); + +private: + QState *makeState(QState *parentState, const QString &animationFileName); + + StickMan *m_stickMan; + QStateMachine *m_machine; + QAnimationGroup *m_animationGroup; + GraphicsView *m_keyReceiver; + + QState *m_alive; + QState *m_dead; + QState *m_idle; +}; + +#endif diff --git a/examples/animation/stickman/main.cpp b/examples/animation/stickman/main.cpp new file mode 100644 index 0000000000..08df766509 --- /dev/null +++ b/examples/animation/stickman/main.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "animation.h" +#include "node.h" +#include "lifecycle.h" +#include "stickman.h" +#include "graphicsview.h" + +#include <QtCore> +#include <QtGui> + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(stickman); + QApplication app(argc, argv); + + StickMan *stickMan = new StickMan; + stickMan->setDrawSticks(false); + + QGraphicsTextItem *textItem = new QGraphicsTextItem(); + textItem->setHtml("<font color=\"white\"><b>Stickman</b>" + "<p>" + "Tell the stickman what to do!" + "</p>" + "<p><i>" + "<li>Press <font color=\"purple\">J</font> to make the stickman jump.</li>" + "<li>Press <font color=\"purple\">D</font> to make the stickman dance.</li>" + "<li>Press <font color=\"purple\">C</font> to make him chill out.</li>" + "<li>When you are done, press <font color=\"purple\">Escape</font>.</li>" + "</i></p>" + "<p>If he is unlucky, the stickman will get struck by lightning, and never jump, dance or chill out again." + "</p></font>"); + qreal w = textItem->boundingRect().width(); + QRectF stickManBoundingRect = stickMan->mapToScene(stickMan->boundingRect()).boundingRect(); + textItem->setPos(-w / 2.0, stickManBoundingRect.bottom() + 25.0); + + QGraphicsScene scene; + scene.addItem(stickMan); + scene.addItem(textItem); + scene.setBackgroundBrush(Qt::black); + + GraphicsView view; + view.setRenderHints(QPainter::Antialiasing); + view.setTransformationAnchor(QGraphicsView::NoAnchor); + view.setScene(&scene); + view.show(); + view.setFocus(); + + QRectF sceneRect = scene.sceneRect(); + // making enough room in the scene for stickman to jump and die + view.resize(sceneRect.width() + 100, sceneRect.height() + 100); + view.setSceneRect(sceneRect); + + LifeCycle cycle(stickMan, &view); + cycle.setDeathAnimation(":/animations/dead"); + + cycle.addActivity(":/animations/jumping", Qt::Key_J); + cycle.addActivity(":/animations/dancing", Qt::Key_D); + cycle.addActivity(":/animations/chilling", Qt::Key_C); + cycle.start(); + + return app.exec(); +} diff --git a/examples/animation/stickman/node.cpp b/examples/animation/stickman/node.cpp new file mode 100644 index 0000000000..3077dffb12 --- /dev/null +++ b/examples/animation/stickman/node.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "node.h" +#include "stickman.h" + +#include <QRectF> +#include <QPainter> +#include <QGraphicsSceneMouseEvent> + +Node::Node(const QPointF &pos, QGraphicsItem *parent) + : QGraphicsObject(parent), m_dragging(false) +{ + setPos(pos); + setFlag(QGraphicsItem::ItemSendsGeometryChanges); +} + +Node::~Node() +{ +} + +QRectF Node::boundingRect() const +{ + return QRectF(-6.0, -6.0, 12.0, 12.0); +} + +void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->setPen(Qt::white); + painter->drawEllipse(QPointF(0.0, 0.0), 5.0, 5.0); +} + +QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == QGraphicsItem::ItemPositionChange) + emit positionChanged(); + + return QGraphicsObject::itemChange(change, value); +} + +void Node::mousePressEvent(QGraphicsSceneMouseEvent *) +{ + m_dragging = true; +} + +void Node::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_dragging) + setPos(mapToParent(event->pos())); +} + +void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *) +{ + m_dragging = false; +} diff --git a/examples/animation/stickman/node.h b/examples/animation/stickman/node.h new file mode 100644 index 0000000000..cefb3a81ac --- /dev/null +++ b/examples/animation/stickman/node.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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$ +** +****************************************************************************/ + +#ifndef NODE_H +#define NODE_H + +#include <QGraphicsItem> + +class Node: public QGraphicsObject +{ + Q_OBJECT +public: + Node(const QPointF &pos, QGraphicsItem *parent = 0); + ~Node(); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +signals: + void positionChanged(); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + + void mousePressEvent(QGraphicsSceneMouseEvent *); + void mouseMoveEvent(QGraphicsSceneMouseEvent *); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *); + +private: + bool m_dragging; +}; + +#endif diff --git a/examples/animation/stickman/stickman.cpp b/examples/animation/stickman/stickman.cpp new file mode 100644 index 0000000000..8b474579c2 --- /dev/null +++ b/examples/animation/stickman/stickman.cpp @@ -0,0 +1,337 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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 "stickman.h" +#include "node.h" + +#include <QPainter> +#include <QTimer> + +#define _USE_MATH_DEFINES +#include <math.h> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +static const qreal Coords[NodeCount * 2] = { + 0.0, -150.0, // head, #0 + + 0.0, -100.0, // body pentagon, top->bottom, left->right, #1 - 5 + -50.0, -50.0, + 50.0, -50.0, + -25.0, 50.0, + 25.0, 50.0, + + -100.0, 0.0, // right arm, #6 - 7 + -125.0, 50.0, + + 100.0, 0.0, // left arm, #8 - 9 + 125.0, 50.0, + + -35.0, 75.0, // lower body, #10 - 11 + 35.0, 75.0, + + -25.0, 200.0, // right leg, #12 - 13 + -30.0, 300.0, + + 25.0, 200.0, // left leg, #14 - 15 + 30.0, 300.0 + +}; + +static const int Bones[BoneCount * 2] = { + 0, 1, // neck + + 1, 2, // body + 1, 3, + 1, 4, + 1, 5, + 2, 3, + 2, 4, + 2, 5, + 3, 4, + 3, 5, + 4, 5, + + 2, 6, // right arm + 6, 7, + + 3, 8, // left arm + 8, 9, + + 4, 10, // lower body + 4, 11, + 5, 10, + 5, 11, + 10, 11, + + 10, 12, // right leg + 12, 13, + + 11, 14, // left leg + 14, 15 + +}; + +StickMan::StickMan() +{ + m_sticks = true; + m_isDead = false; + m_pixmap = QPixmap("images/head.png"); + m_penColor = Qt::white; + m_fillColor = Qt::black; + + // Set up start position of limbs + for (int i=0; i<NodeCount; ++i) { + m_nodes[i] = new Node(QPointF(Coords[i * 2], Coords[i * 2 + 1]), this); + connect(m_nodes[i], SIGNAL(positionChanged()), this, SLOT(childPositionChanged())); + } + + for (int i=0; i<BoneCount; ++i) { + int n1 = Bones[i * 2]; + int n2 = Bones[i * 2 + 1]; + + Node *node1 = m_nodes[n1]; + Node *node2 = m_nodes[n2]; + + QPointF dist = node1->pos() - node2->pos(); + m_perfectBoneLengths[i] = sqrt(pow(dist.x(),2) + pow(dist.y(),2)); + } + + startTimer(10); +} + +StickMan::~StickMan() +{ +} + +void StickMan::childPositionChanged() +{ + prepareGeometryChange(); +} + +void StickMan::setDrawSticks(bool on) +{ + m_sticks = on; + for (int i=0;i<nodeCount();++i) { + Node *node = m_nodes[i]; + node->setVisible(on); + } +} + +QRectF StickMan::boundingRect() const +{ + // account for head radius=50.0 plus pen which is 5.0 + return childrenBoundingRect().adjusted(-55.0, -55.0, 55.0, 55.0); +} + +int StickMan::nodeCount() const +{ + return NodeCount; +} + +Node *StickMan::node(int idx) const +{ + if (idx >= 0 && idx < NodeCount) + return m_nodes[idx]; + else + return 0; +} + +void StickMan::timerEvent(QTimerEvent *) +{ + update(); +} + +void StickMan::stabilize() +{ + static const qreal threshold = 0.001; + + for (int i=0; i<BoneCount; ++i) { + int n1 = Bones[i * 2]; + int n2 = Bones[i * 2 + 1]; + + Node *node1 = m_nodes[n1]; + Node *node2 = m_nodes[n2]; + + QPointF pos1 = node1->pos(); + QPointF pos2 = node2->pos(); + + QPointF dist = pos1 - pos2; + qreal length = sqrt(pow(dist.x(),2) + pow(dist.y(),2)); + qreal diff = (length - m_perfectBoneLengths[i]) / length; + + QPointF p = dist * (0.5 * diff); + if (p.x() > threshold && p.y() > threshold) { + pos1 -= p; + pos2 += p; + + node1->setPos(pos1); + node2->setPos(pos2); + } + } +} + +QPointF StickMan::posFor(int idx) const +{ + return m_nodes[idx]->pos(); +} + +//#include <QTime> +void StickMan::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + /* static int frames = 0; + static QTime time; + if (frames++ % 100 == 0) { + frames = 1; + time.restart(); + } + + if (time.elapsed() > 0) { + painter->setPen(Qt::white); + painter->drawText(0, 0, QString::number(frames / (time.elapsed() / 1000.0))); + }*/ + + stabilize(); + if (m_sticks) { + painter->setPen(Qt::white); + for (int i=0; i<BoneCount; ++i) { + int n1 = Bones[i * 2]; + int n2 = Bones[i * 2 + 1]; + + Node *node1 = m_nodes[n1]; + Node *node2 = m_nodes[n2]; + + painter->drawLine(node1->pos(), node2->pos()); + } + } else { + // first bone is neck and will be used for head + + QPainterPath path; + path.moveTo(posFor(0)); + path.lineTo(posFor(1)); + + // right arm + path.lineTo(posFor(2)); + path.lineTo(posFor(6)); + path.lineTo(posFor(7)); + + // left arm + path.moveTo(posFor(3)); + path.lineTo(posFor(8)); + path.lineTo(posFor(9)); + + // body + path.moveTo(posFor(2)); + path.lineTo(posFor(4)); + path.lineTo(posFor(10)); + path.lineTo(posFor(11)); + path.lineTo(posFor(5)); + path.lineTo(posFor(3)); + path.lineTo(posFor(1)); + + // right leg + path.moveTo(posFor(10)); + path.lineTo(posFor(12)); + path.lineTo(posFor(13)); + + // left leg + path.moveTo(posFor(11)); + path.lineTo(posFor(14)); + path.lineTo(posFor(15)); + + painter->setPen(QPen(m_penColor, 5.0, Qt::SolidLine, Qt::RoundCap)); + painter->drawPath(path); + + { + int n1 = Bones[0]; + int n2 = Bones[1]; + Node *node1 = m_nodes[n1]; + Node *node2 = m_nodes[n2]; + + QPointF dist = node2->pos() - node1->pos(); + + qreal sinAngle = dist.x() / sqrt(pow(dist.x(), 2) + pow(dist.y(), 2)); + qreal angle = asin(sinAngle) * 180.0 / M_PI; + + QPointF headPos = node1->pos(); + painter->translate(headPos); + painter->rotate(-angle); + + painter->setBrush(m_fillColor); + painter->drawEllipse(QPointF(0,0), 50.0, 50.0); + + painter->setBrush(m_penColor); + painter->setPen(QPen(m_penColor, 2.5, Qt::SolidLine, Qt::RoundCap)); + + // eyes + if (m_isDead) { + painter->drawLine(-30.0, -30.0, -20.0, -20.0); + painter->drawLine(-20.0, -30.0, -30.0, -20.0); + + painter->drawLine(20.0, -30.0, 30.0, -20.0); + painter->drawLine(30.0, -30.0, 20.0, -20.0); + } else { + painter->drawChord(QRectF(-30.0, -30.0, 25.0, 70.0), 30.0*16, 120.0*16); + painter->drawChord(QRectF(5.0, -30.0, 25.0, 70.0), 30.0*16, 120.0*16); + } + + // mouth + if (m_isDead) { + painter->drawLine(-28.0, 2.0, 29.0, 2.0); + } else { + painter->setBrush(QColor(128, 0, 64 )); + painter->drawChord(QRectF(-28.0, 2.0-55.0/2.0, 57.0, 55.0), 0.0, -180.0*16); + } + + // pupils + if (!m_isDead) { + painter->setPen(QPen(m_fillColor, 1.0, Qt::SolidLine, Qt::RoundCap)); + painter->setBrush(m_fillColor); + painter->drawEllipse(QPointF(-12.0, -25.0), 5.0, 5.0); + painter->drawEllipse(QPointF(22.0, -25.0), 5.0, 5.0); + } + } + } +} + + + diff --git a/examples/animation/stickman/stickman.h b/examples/animation/stickman/stickman.h new file mode 100644 index 0000000000..eeebbef283 --- /dev/null +++ b/examples/animation/stickman/stickman.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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 Nokia Corporation and its Subsidiary(-ies) 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$ +** +****************************************************************************/ + +#ifndef STICKMAN_H +#define STICKMAN_H + +#include <QGraphicsObject> + +static const int NodeCount = 16; +static const int BoneCount = 24; + +class Node; +QT_BEGIN_NAMESPACE +QT_END_NAMESPACE +class StickMan: public QGraphicsObject +{ + Q_OBJECT + Q_PROPERTY(QColor penColor WRITE setPenColor READ penColor) + Q_PROPERTY(QColor fillColor WRITE setFillColor READ fillColor) + Q_PROPERTY(bool isDead WRITE setIsDead READ isDead) +public: + StickMan(); + ~StickMan(); + + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + int nodeCount() const; + Node *node(int idx) const; + + void setDrawSticks(bool on); + bool drawSticks() const { return m_sticks; } + + QColor penColor() const { return m_penColor; } + void setPenColor(const QColor &color) { m_penColor = color; } + + QColor fillColor() const { return m_fillColor; } + void setFillColor(const QColor &color) { m_fillColor = color; } + + bool isDead() const { return m_isDead; } + void setIsDead(bool isDead) { m_isDead = isDead; } + +public slots: + void stabilize(); + void childPositionChanged(); + +protected: + void timerEvent(QTimerEvent *e); + +private: + + QPointF posFor(int idx) const; + + Node *m_nodes[NodeCount]; + qreal m_perfectBoneLengths[BoneCount]; + + uint m_sticks : 1; + uint m_isDead : 1; + uint m_reserved : 30; + + QPixmap m_pixmap; + QColor m_penColor; + QColor m_fillColor; +}; + +#endif // STICKMAN_H diff --git a/examples/animation/stickman/stickman.pro b/examples/animation/stickman/stickman.pro new file mode 100644 index 0000000000..a4f5aafb2d --- /dev/null +++ b/examples/animation/stickman/stickman.pro @@ -0,0 +1,24 @@ +HEADERS += stickman.h \ + animation.h \ + node.h \ + lifecycle.h \ + graphicsview.h +SOURCES += main.cpp \ + stickman.cpp \ + animation.cpp \ + node.cpp \ + lifecycle.cpp \ + graphicsview.cpp + +RESOURCES += stickman.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/stickman +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS stickman.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/qtbase/animation/stickman +INSTALLS += target sources + +symbian { + TARGET.UID3 = 0xA000E3F9 + include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +} diff --git a/examples/animation/stickman/stickman.qrc b/examples/animation/stickman/stickman.qrc new file mode 100644 index 0000000000..e5d66cf2c7 --- /dev/null +++ b/examples/animation/stickman/stickman.qrc @@ -0,0 +1,8 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>animations/chilling</file> + <file>animations/dancing</file> + <file>animations/dead</file> + <file>animations/jumping</file> +</qresource> +</RCC>
\ No newline at end of file |