aboutsummaryrefslogtreecommitdiffstats
path: root/examples/statemachine/moveblocks/moveblocks.py
diff options
context:
space:
mode:
Diffstat (limited to 'examples/statemachine/moveblocks/moveblocks.py')
-rw-r--r--examples/statemachine/moveblocks/moveblocks.py222
1 files changed, 222 insertions, 0 deletions
diff --git a/examples/statemachine/moveblocks/moveblocks.py b/examples/statemachine/moveblocks/moveblocks.py
new file mode 100644
index 000000000..0d52c5b00
--- /dev/null
+++ b/examples/statemachine/moveblocks/moveblocks.py
@@ -0,0 +1,222 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the examples/statemachine/moveblocks example from Qt v6.x"""
+
+import sys
+
+from PySide6.QtCore import (QAbstractAnimation, QEasingCurve, QEvent, QObject,
+ QParallelAnimationGroup, QPropertyAnimation,
+ QRandomGenerator, QRect, QSequentialAnimationGroup,
+ Qt, QTimer)
+from PySide6.QtGui import QPainter, QResizeEvent
+from PySide6.QtWidgets import (QApplication, QGraphicsView, QGraphicsScene,
+ QGraphicsWidget, QStyleOptionGraphicsItem,
+ QWidget)
+from PySide6.QtStateMachine import (QAbstractTransition, QState, QStateMachine)
+
+
+StateSwitchType = QEvent.Type(QEvent.Type.User + 256)
+
+
+class StateSwitchEvent(QEvent):
+ def __init__(self, rand: int = 0) -> None:
+ super().__init__(StateSwitchType)
+ self._rand = rand
+
+ def rand(self) -> int:
+ return self._rand
+
+
+class QGraphicsRectWidget(QGraphicsWidget):
+ def __init__(self):
+ super().__init__()
+
+ def paint(self, painter: QPainter,
+ option: QStyleOptionGraphicsItem, widget: QWidget | None = None):
+ painter.fillRect(self.rect(), Qt.blue)
+
+
+class StateSwitchTransition(QAbstractTransition):
+ def __init__(self, rand: int = 0) -> None:
+ super().__init__()
+ self._rand = rand
+
+ def eventTest(self, event: QEvent) -> bool:
+ return event.type() == StateSwitchType and event.rand() == self._rand
+
+ def onTransition(self, event: QEvent):
+ pass
+
+
+class StateSwitcher(QState):
+ def __init__(self, machine: QStateMachine) -> None:
+ super().__init__(machine)
+ self._state_count = 0
+ self._last_index = 0
+ self.rg = QRandomGenerator.global_()
+
+ def onEntry(self, event: QEvent) -> None:
+ while True:
+ n = int(self.rg.bounded(self._state_count)) + 1
+ if n != self._last_index:
+ break
+ self._last_index = n
+ self.event = StateSwitchEvent(n)
+ self.machine().postEvent(self.event)
+
+ def onExit(self, event: QEvent) -> None:
+ pass
+
+ def addState(self, state: QState, animation: QAbstractAnimation) -> None:
+ self._state_count += 1
+ trans = StateSwitchTransition(self._state_count)
+ trans.setTargetState(state)
+ self.addTransition(trans)
+ trans.addAnimation(animation)
+
+
+def createGeometryState(w1: QObject, rect1: QRect,
+ w2: QObject, rect2: QRect,
+ w3: QObject, rect3: QRect,
+ w4: QObject, rect4: QRect, parent: QState) -> QState:
+ result = 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(QGraphicsView):
+ def __init__(self, scene: QGraphicsScene, parent: QWidget | None = None):
+ super().__init__(scene, parent)
+
+ def resizeEvent(self, event: QResizeEvent) -> None:
+ self.fitInView(self.sceneRect())
+ super().resizeEvent(event)
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+ button1, button2 = QGraphicsRectWidget(), QGraphicsRectWidget()
+ button3, button4 = QGraphicsRectWidget(), QGraphicsRectWidget()
+
+ button2.setZValue(1)
+ button3.setZValue(2)
+ button4.setZValue(3)
+
+ scene = QGraphicsScene(0, 0, 300, 300)
+ scene.setBackgroundBrush(Qt.black)
+ scene.addItem(button1)
+ scene.addItem(button2)
+ scene.addItem(button3)
+ scene.addItem(button4)
+
+ window = GraphicsView(scene)
+ window.setFrameStyle(0)
+ window.setAlignment(Qt.AlignLeft | Qt.AlignTop)
+ window.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+ window.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+
+ machine = QStateMachine()
+
+ group = QState()
+ group.setObjectName("group")
+ timer = QTimer()
+ timer.setInterval(1250)
+ timer.setSingleShot(True)
+
+ group.entered.connect(timer.start)
+
+ state1, state2, state3 = QState(), QState(), QState()
+ state4, state5, state6 = QState(), QState(), QState()
+ state7 = QState()
+
+ 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)
+
+ animation_group = QParallelAnimationGroup()
+ sub_group = QSequentialAnimationGroup()
+
+ anim = QPropertyAnimation(button4, b"geometry")
+ anim.setDuration(1000)
+ anim.setEasingCurve(QEasingCurve.OutElastic)
+ animation_group.addAnimation(anim)
+
+ sub_group = QSequentialAnimationGroup(animation_group)
+ sub_group.addPause(100)
+ anim = QPropertyAnimation(button3, b"geometry")
+ anim.setDuration(1000)
+ anim.setEasingCurve(QEasingCurve.OutElastic)
+ sub_group.addAnimation(anim)
+
+ sub_group = QSequentialAnimationGroup(animation_group)
+ sub_group.addPause(150)
+ anim = QPropertyAnimation(button2, b"geometry")
+ anim.setDuration(1000)
+ anim.setEasingCurve(QEasingCurve.OutElastic)
+ sub_group.addAnimation(anim)
+
+ sub_group = QSequentialAnimationGroup(animation_group)
+ sub_group.addPause(200)
+ anim = QPropertyAnimation(button1, b"geometry")
+ anim.setDuration(1000)
+ anim.setEasingCurve(QEasingCurve.OutElastic)
+ sub_group.addAnimation(anim)
+
+ state_switcher = StateSwitcher(machine)
+ state_switcher.setObjectName("state_switcher")
+ group.addTransition(timer.timeout, state_switcher)
+ state_switcher.addState(state1, animation_group)
+ state_switcher.addState(state2, animation_group)
+ state_switcher.addState(state3, animation_group)
+ state_switcher.addState(state4, animation_group)
+ state_switcher.addState(state5, animation_group)
+ state_switcher.addState(state6, animation_group)
+ state_switcher.addState(state7, animation_group)
+
+ machine.addState(group)
+ machine.setInitialState(group)
+ machine.start()
+
+ window.resize(300, 300)
+ window.show()
+
+ sys.exit(app.exec())