main.cpp Example File

animation/moveblocks/main.cpp
 /****************************************************************************
 **
 ** Copyright (C) 2016 The Qt Company Ltd.
 ** Contact: https://www.qt.io/licensing/
 **
 ** This file is part of the QtCore module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:BSD$
 ** Commercial License Usage
 ** Licensees holding valid commercial Qt licenses may use this file in
 ** accordance with the commercial license agreement provided with the
 ** Software or, alternatively, in accordance with the terms contained in
 ** a written agreement between you and The Qt Company. For licensing terms
 ** and conditions see https://www.qt.io/terms-conditions. For further
 ** information use the contact form at https://www.qt.io/contact-us.
 **
 ** BSD License Usage
 ** Alternatively, you may use this file under the terms of the BSD license
 ** as follows:
 **
 ** "Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions are
 ** met:
 **   * Redistributions of source code must retain the above copyright
 **     notice, this list of conditions and the following disclaimer.
 **   * Redistributions in binary form must reproduce the above copyright
 **     notice, this list of conditions and the following disclaimer in
 **     the documentation and/or other materials provided with the
 **     distribution.
 **   * Neither the name of The Qt Company Ltd nor the names of its
 **     contributors may be used to endorse or promote products derived
 **     from this software without specific prior written permission.
 **
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
 **
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/

 #include <QtCore>
 #include <QtWidgets>

 class StateSwitchEvent: public QEvent
 {
 public:
     StateSwitchEvent()
         : QEvent(Type(StateSwitchType))
     {
     }

     explicit StateSwitchEvent(int rand)
         : QEvent(Type(StateSwitchType)),
           m_rand(rand)
     {
     }

     enum { StateSwitchType = QEvent::User + 256 };

     int rand() const { return m_rand; }

 private:
     int m_rand;
 };

 class QGraphicsRectWidget : public QGraphicsWidget
 {
 public:
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *,
                QWidget *) override
     {
         painter->fillRect(rect(), Qt::blue);
     }
 };

 class StateSwitchTransition: public QAbstractTransition
 {
 public:
     StateSwitchTransition(int rand)
         : QAbstractTransition(),
           m_rand(rand)
     {
     }

 protected:
     bool eventTest(QEvent *event) override
     {
         return (event->type() == QEvent::Type(StateSwitchEvent::StateSwitchType))
             && (static_cast<StateSwitchEvent *>(event)->rand() == m_rand);
     }

     void onTransition(QEvent *) override {}

 private:
     int m_rand;
 };

 class StateSwitcher : public QState
 {
     Q_OBJECT
 public:
     StateSwitcher(QStateMachine *machine)
         : QState(machine), m_stateCount(0), m_lastIndex(0)
     { }

     void onEntry(QEvent *) override
     {
         int n;
         while ((n = QRandomGenerator::global()->bounded(m_stateCount) + 1) == m_lastIndex)
         { }
         m_lastIndex = n;
         machine()->postEvent(new StateSwitchEvent(n));
     }
     void onExit(QEvent *) override {}

     void addState(QState *state, QAbstractAnimation *animation) {
         StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount);
         trans->setTargetState(state);
         addTransition(trans);
         trans->addAnimation(animation);
     }

 private:
     int m_stateCount;
     int m_lastIndex;
 };

 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;
 }

 class GraphicsView : public QGraphicsView
 {
     Q_OBJECT
 public:
     GraphicsView(QGraphicsScene *scene, QWidget *parent = NULL) : QGraphicsView(scene, parent)
     {
     }

 protected:
     void resizeEvent(QResizeEvent *event) override
     {
         fitInView(scene()->sceneRect());
         QGraphicsView::resizeEvent(event);
     }
 };

 int main(int argc, char **argv)
 {
     QApplication app(argc, argv);

     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);
     GraphicsView window(&scene);
     window.setFrameStyle(0);
     window.setAlignment(Qt::AlignLeft | Qt::AlignTop);
     window.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     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()));

     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);
     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);
     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);

     QParallelAnimationGroup animationGroup;
     QSequentialAnimationGroup *subGroup;

     QPropertyAnimation *anim = new QPropertyAnimation(button4, "geometry");
     anim->setDuration(1000);
     anim->setEasingCurve(QEasingCurve::OutElastic);
     animationGroup.addAnimation(anim);

     subGroup = new QSequentialAnimationGroup(&animationGroup);
     subGroup->addPause(100);
     anim = new QPropertyAnimation(button3, "geometry");
     anim->setDuration(1000);
     anim->setEasingCurve(QEasingCurve::OutElastic);
     subGroup->addAnimation(anim);

     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);

     StateSwitcher *stateSwitcher = new StateSwitcher(&machine);
     stateSwitcher->setObjectName("stateSwitcher");
     group->addTransition(&timer, SIGNAL(timeout()), stateSwitcher);
     stateSwitcher->addState(state1, &animationGroup);
     stateSwitcher->addState(state2, &animationGroup);
     stateSwitcher->addState(state3, &animationGroup);
     stateSwitcher->addState(state4, &animationGroup);
     stateSwitcher->addState(state5, &animationGroup);
     stateSwitcher->addState(state6, &animationGroup);
     stateSwitcher->addState(state7, &animationGroup);

     machine.addState(group);
     machine.setInitialState(group);
     machine.start();

     window.resize(300, 300);
     window.show();

     return app.exec();
 }

 #include "main.moc"