/**************************************************************************** ** ** 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 #include #include #include 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 = nullptr) : QGraphicsWidget(parent), _pix(pixmap) { setAcceptHoverEvents(true); setCacheMode(DeviceCoordinateCache); } QRectF boundingRect() const override { return QRectF(-65, -65, 130, 130); } QPainterPath shape() const override { QPainterPath path; path.addEllipse(boundingRect()); return path; } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) override { 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 *) override { emit pressed(); update(); } void mouseReleaseEvent(QGraphicsSceneMouseEvent *) override { update(); } private: QPixmap _pix; }; class View : public QGraphicsView { public: View(QGraphicsScene *scene) : QGraphicsView(scene) { } protected: void resizeEvent(QResizeEvent *event) override { 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 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->setTransform(QTransform::fromScale(0.75, 0.75), true); 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(qCos((i / 63.0) * 6.28) * 250, qSin((i / 63.0) * 6.28) * 250)); // Figure 8 figure8State->assignProperty(item, "pos", QPointF(qSin((i / 63.0) * 6.28) * 250, qSin(((i * 2)/63.0) * 6.28) * 250)); // Random randomState->assignProperty(item, "pos", QPointF(-250 + QRandomGenerator::global()->bounded(500), -250 + QRandomGenerator::global()->bounded(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, &Button::pressed, ellipseState); trans->addAnimation(group); trans = rootState->addTransition(figure8Button, &Button::pressed, figure8State); trans->addAnimation(group); trans = rootState->addTransition(randomButton, &Button::pressed, randomState); trans->addAnimation(group); trans = rootState->addTransition(tiledButton, &Button::pressed, tiledState); trans->addAnimation(group); trans = rootState->addTransition(centeredButton, &Button::pressed, centeredState); trans->addAnimation(group); QTimer timer; timer.start(125); timer.setSingleShot(true); trans = rootState->addTransition(&timer, &QTimer::timeout, ellipseState); trans->addAnimation(group); states.start(); #ifdef QT_KEYPAD_NAVIGATION QApplication::setNavigationMode(Qt::NavigationModeCursorAuto); #endif return app.exec(); } #include "main.moc"