summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeir Vattekar <geir.vattekar@trolltech.com>2009-06-29 12:40:17 (GMT)
committerGeir Vattekar <geir.vattekar@trolltech.com>2009-06-29 13:00:59 (GMT)
commit98c8e465a62b47051d35f998a3cdea54dfede3ad (patch)
tree76cfddaad1803900e5e00cabac73f3d74acef9aa
parent9dd82fcebc50ca802e9e24a50283152e1dc35508 (diff)
downloadQt-98c8e465a62b47051d35f998a3cdea54dfede3ad.zip
Qt-98c8e465a62b47051d35f998a3cdea54dfede3ad.tar.gz
Qt-98c8e465a62b47051d35f998a3cdea54dfede3ad.tar.bz2
Doc: Documented the Move Blocks example.
Reviewed-by: Andreas Aardal Hanssen
-rw-r--r--doc/src/examples.qdoc1
-rw-r--r--doc/src/examples/moveblocks.qdoc228
-rw-r--r--doc/src/images/move-blocks-chart.pngbin0 -> 15740 bytes
-rw-r--r--doc/src/images/moveblocks-example.pngbin0 -> 4532 bytes
-rw-r--r--examples/animation/moveblocks/main.cpp36
5 files changed, 261 insertions, 4 deletions
diff --git a/doc/src/examples.qdoc b/doc/src/examples.qdoc
index 1f20b91..f6bb877 100644
--- a/doc/src/examples.qdoc
+++ b/doc/src/examples.qdoc
@@ -90,6 +90,7 @@
\section1 Animation
\list
+ \o \l{animation/moveblocks}{Move Blocks}\raisedaster
\o \l{animation/stickman}{Stick man}\raisedaster
\endlist
diff --git a/doc/src/examples/moveblocks.qdoc b/doc/src/examples/moveblocks.qdoc
new file mode 100644
index 0000000..2bdcca5
--- /dev/null
+++ b/doc/src/examples/moveblocks.qdoc
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example animation/moveblocks
+ \title Move Blocks Example
+
+ The Move Blocks example shows how to animate items in a
+ QGraphicsScene using a QStateMachine with a custom transition.
+
+ \image moveblocks-example.png
+
+ The example animates the blue blocks that you can see in the image
+ above. The animation moves the blocks between four preset positions.
+
+ The example consists of the following classes:
+
+ \list
+ \o \c StateSwitcher inherits QState and can add
+ \c {StateSwitchTransition}s to other states.
+ When entered, it will randomly transition to one of these
+ states.
+ \o \c StateSwitchTransition is a custom transition that
+ triggers on \c{StateSwitchEvent}s.
+ \o \c StateSwitchEvent is a QEvent that trigger \c{StateSwitchTransition}s.
+ \o \c QGraphicsRectWidget is a QGraphicsWidget that simply
+ paints its background in a solid \l{Qt::}{blue} color.
+ \endlist
+
+ The blocks are instances of \c QGraphicsRectWidget and are
+ animated in a QGraphicsScene. We do this by building a state
+ graph, which we insert animations into. The graph is then executed
+ in a QStateMachine. All this is done in \c main().
+ Let's look at the \c main() function first.
+
+ \section1 The \c main() Function
+
+ After QApplication has been initialized, we set up the
+ QGraphicsScene with its \c{QGraphicsRectWidget}s.
+
+ \snippet examples/animation/moveblocks/main.cpp 1
+
+ After adding the scene to a QGraphicsView, it is time to build the
+ state graph. Let's first look at a statechart of what we are
+ trying to build.
+
+ \image move-blocks-chart.png
+
+ Note that the \c group has seven sub states, but we have only
+ included three of them in the diagram. The code that builds this
+ graph will be examined line-by-line, and will show how the graph
+ works. First off, we construct the \c group state:
+
+ \snippet examples/animation/moveblocks/main.cpp 2
+
+ The timer is used to add a delay between each time the blocks are
+ moved. The timer is started when \c group is entered. As we will
+ see later, \c group has a transition back to the \c StateSwitcher
+ when the timer times out. \c group is the initial state in the
+ machine, so an animation will be scheduled when the example is
+ started.
+
+ \snippet examples/animation/moveblocks/main.cpp 3
+ \dots
+ \snippet examples/animation/moveblocks/main.cpp 4
+
+ \c createGeometryState() returns a QState that will set the
+ geometry of our items upon entry. It also assigns \c group as the
+ parent of this state.
+
+ A QPropertyAnimation inserted into a transition will use the
+ values assigned to a QState (with QState::assignProperty()), i.e.,
+ the animation will interpolate between the current values of the
+ properties and the values in the target state. We add animated
+ transitions to the state graph later.
+
+ \snippet examples/animation/moveblocks/main.cpp 5
+
+ We move the items in parallel. Each item is added to \c
+ animationGroup, which is the animation that is inserted into the
+ transitions.
+
+ \snippet examples/animation/moveblocks/main.cpp 6
+
+ The sequential animation group, \c subGroup, helps us insert a
+ delay between the animation of each item.
+
+ \snippet examples/animation/moveblocks/main.cpp 7
+ \dots
+ \snippet examples/animation/moveblocks/main.cpp 8
+
+ A StateSwitchTransition is added to the state switcher
+ in \c StateSwitcher::addState(). We also add the animation in this
+ function. Since QPropertyAnimation uses the values from the
+ states, we can insert the same QPropertyAnimation instance in all
+ \c {StateSwitchTransition}s.
+
+ As mentioned previously, we add a transition to the state switcher
+ that triggers when the timer times out.
+
+ \snippet examples/animation/moveblocks/main.cpp 9
+
+ Finally, we can create the state machine, add our initial state,
+ and start execution of the state graph.
+
+ \section2 The \c createGemetryState() Function
+
+ In \c createGeometryState(), we set up the geometry for each
+ graphics item.
+
+ \snippet examples/animation/moveblocks/main.cpp 13
+
+ As mentioned before, QAbstractTransition will set up an animation
+ added with \l{QAbstractTransition::}{addAnimation()} using
+ property values set with \l{QState::}{assignProperty()}.
+
+ \section1 The StateSwitcher Class
+
+ \c StateSwitcher has state switch transitions to each \l{QState}s
+ we created with \c createGemetryState(). Its job is to transition
+ to one of these states at random when it is entered.
+
+ All functions in \c StateSwitcher are inlined. We'll step through
+ its definition.
+
+ \snippet examples/animation/moveblocks/main.cpp 10
+
+ \c StateSwitcher is a state designed for a particular purpose and
+ will always be a top-level state. We use \c m_stateCount to keep
+ track of how many states we are managing, and \c m_lastIndex to
+ remember which state was the last state to which we transitioned.
+
+ \snippet examples/animation/moveblocks/main.cpp 11
+
+ We select the next state we are going to transition to, and post a
+ \c StateSwitchEvent, which we know will trigger the \c
+ StateSwitchTransition to the selected state.
+
+ \snippet examples/animation/moveblocks/main.cpp 12
+
+ This is where the magic happens. We assign a number to each state
+ added. This number is given to both a StateSwitchTransition and to
+ StateSwitchEvents. As we have seen, state switch events will
+ trigger a transition with the same number.
+
+ \section1 The StateSwitchTransition Class
+
+ \c StateSwitchTransition inherits QAbstractTransition and triggers
+ on \c{StateSwitchEvent}s. It contains only inline functions, so
+ let's take a look at its \l{QAbstractTransition::}{eventTest()}
+ function, which is the only function that we define..
+
+ \snippet examples/animation/moveblocks/main.cpp 14
+
+ \c eventTest is called by QStateMachine when it checks whether a
+ transition should be triggered--a return value of true means that
+ it will. We simply check if our assigned number is equal to the
+ event's number (in which case we fire away).
+
+ \section1 The StateSwitchEvent Class
+
+ \c StateSwitchEvent inherits QEvent, and holds a number that has
+ been assigned to a state and state switch transition by \c
+ StateSwitcher. We have already seen how it is used to trigger \c
+ \c{StateSwitchTransition}s in \c StateSwitcher.
+
+ \snippet examples/animation/moveblocks/main.cpp 15
+
+ We only have inlined functions in this class, so a look at its
+ definition will do.
+
+ \section1 The QGraphicsRectWidget Class
+
+ QGraphicsRectWidget inherits QGraphicsWidget and simply paints its
+ \l{QWidget::}{rect()} blue. We inline \l{QWidget::}{paintEvent()},
+ which is the only function we define. Here is the
+ QGraphicsRectWidget class definition:
+
+ \snippet examples/animation/moveblocks/main.cpp 16
+
+ \section1 Moving On
+
+ The technique shown in this example works equally well for all
+ \l{QPropertyAnimation}s. As long as the value to be animated is a
+ Qt property, you can insert an animation of it into a state graph.
+
+ QState::addAnimation() takes a QAbstractAnimation, so any type
+ of animation can be inserted into the graph.
+*/
+
diff --git a/doc/src/images/move-blocks-chart.png b/doc/src/images/move-blocks-chart.png
new file mode 100644
index 0000000..fd0c165
--- /dev/null
+++ b/doc/src/images/move-blocks-chart.png
Binary files differ
diff --git a/doc/src/images/moveblocks-example.png b/doc/src/images/moveblocks-example.png
new file mode 100644
index 0000000..56353d1
--- /dev/null
+++ b/doc/src/images/moveblocks-example.png
Binary files differ
diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp
index 4843a89..c43e841 100644
--- a/examples/animation/moveblocks/main.cpp
+++ b/examples/animation/moveblocks/main.cpp
@@ -42,6 +42,7 @@
#include <QtCore>
#include <QtGui>
+//![15]
class StateSwitchEvent: public QEvent
{
public:
@@ -63,8 +64,9 @@ public:
private:
int m_rand;
};
+//![15]
-
+//![16]
class QGraphicsRectWidget : public QGraphicsWidget
{
public:
@@ -74,6 +76,7 @@ public:
painter->fillRect(rect(), Qt::blue);
}
};
+//![16]
class StateSwitchTransition: public QAbstractTransition
{
@@ -85,11 +88,13 @@ public:
}
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 *) {}
@@ -97,6 +102,7 @@ private:
int m_rand;
};
+//![10]
class StateSwitcher : public QState
{
Q_OBJECT
@@ -105,7 +111,9 @@ public:
: QState(machine->rootState()), m_machine(machine),
m_stateCount(0), m_lastIndex(0)
{ }
+//![10]
+//![11]
virtual void onEntry(QEvent *)
{
int n;
@@ -115,14 +123,16 @@ public:
m_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:
QStateMachine *m_machine;
@@ -130,6 +140,7 @@ private:
int m_lastIndex;
};
+//![13]
QState *createGeometryState(QObject *w1, const QRect &rect1,
QObject *w2, const QRect &rect2,
QObject *w3, const QRect &rect3,
@@ -145,6 +156,7 @@ QState *createGeometryState(QObject *w1, const QRect &rect1,
return result;
}
+//![13]
int main(int argc, char **argv)
{
@@ -165,6 +177,7 @@ int main(int argc, char **argv)
button3->setObjectName("button3");
button4->setObjectName("button4");
#else
+//![1]
QGraphicsRectWidget *button1 = new QGraphicsRectWidget;
QGraphicsRectWidget *button2 = new QGraphicsRectWidget;
QGraphicsRectWidget *button3 = new QGraphicsRectWidget;
@@ -178,13 +191,14 @@ int main(int argc, char **argv)
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();
@@ -193,7 +207,9 @@ int main(int argc, char **argv)
timer.setInterval(1250);
timer.setSingleShot(true);
QObject::connect(group, SIGNAL(entered()), &timer, SLOT(start()));
+//![2]
+//![3]
QState *state1;
QState *state2;
QState *state3;
@@ -207,6 +223,7 @@ int main(int argc, char **argv)
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),
@@ -232,13 +249,16 @@ int main(int argc, char **argv)
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;
@@ -246,13 +266,16 @@ int main(int argc, char **argv)
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);
@@ -268,21 +291,26 @@ int main(int argc, char **argv)
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();