aboutsummaryrefslogtreecommitdiffstats
path: root/examples/widgets/state-machine
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-01-05 15:58:35 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-01-12 12:28:10 +0000
commit9f2a9aba3aff73e31ea15eb4a7a04b0e50f4ee4e (patch)
tree92dcb0c4f64df8a8375af2e1a9bb1170068c36b2 /examples/widgets/state-machine
parent26c046e521c38bbfc3a263782a3bb74a7c1bf937 (diff)
Move examples from submodule to pyside-setup
Move PySide2 examples that are owned by the Qt Company to a new examples directory. Done-with: Venugopal Shivashankar <Venugopal.Shivashankar@qt.io> Task-number: PYSIDE-363 Change-Id: I14099764d9eef2bc35e067086121427955862e3a Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'examples/widgets/state-machine')
-rwxr-xr-xexamples/widgets/state-machine/eventtrans.py93
-rwxr-xr-xexamples/widgets/state-machine/factstates.py112
-rwxr-xr-xexamples/widgets/state-machine/pingpong.py97
-rwxr-xr-xexamples/widgets/state-machine/rogue.py203
-rwxr-xr-xexamples/widgets/state-machine/trafficlight.py140
-rwxr-xr-xexamples/widgets/state-machine/twowaybutton.py71
6 files changed, 716 insertions, 0 deletions
diff --git a/examples/widgets/state-machine/eventtrans.py b/examples/widgets/state-machine/eventtrans.py
new file mode 100755
index 000000000..68e21a81f
--- /dev/null
+++ b/examples/widgets/state-machine/eventtrans.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com>
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples 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 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$
+##
+#############################################################################
+
+from PySide2.QtWidgets import *
+from PySide2.QtCore import *
+
+class MainWindow(QMainWindow):
+ def __init__(self):
+ super(MainWindow, self).__init__()
+ button = QPushButton(self)
+ button.setGeometry(QRect(100, 100, 100, 100))
+
+ machine = QStateMachine(self)
+ s1 = QState()
+ s1.assignProperty(button, 'text', 'Outside')
+ s2 = QState()
+ s2.assignProperty(button, 'text', 'Inside')
+
+ enterTransition = QEventTransition(button, QEvent.Enter)
+ enterTransition.setTargetState(s2)
+ s1.addTransition(enterTransition)
+
+ leaveTransition = QEventTransition(button, QEvent.Leave)
+ leaveTransition.setTargetState(s1)
+ s2.addTransition(leaveTransition)
+
+ s3 = QState()
+ s3.assignProperty(button, 'text', 'Pressing...')
+
+ pressTransition = QEventTransition(button, QEvent.MouseButtonPress)
+ pressTransition.setTargetState(s3)
+ s2.addTransition(pressTransition)
+
+ releaseTransition = QEventTransition(button, QEvent.MouseButtonRelease)
+ releaseTransition.setTargetState(s2)
+ s3.addTransition(releaseTransition)
+
+ machine.addState(s1)
+ machine.addState(s2)
+ machine.addState(s3)
+
+ machine.setInitialState(s1)
+ machine.start()
+
+ self.setCentralWidget(button)
+ self.show()
+
+if __name__ == '__main__':
+ import sys
+
+ app = QApplication(sys.argv)
+ mainWin = MainWindow()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/state-machine/factstates.py b/examples/widgets/state-machine/factstates.py
new file mode 100755
index 000000000..8550c3f39
--- /dev/null
+++ b/examples/widgets/state-machine/factstates.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com>
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples 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 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$
+##
+#############################################################################
+
+from PySide2.QtWidgets import *
+from PySide2.QtCore import *
+
+class Factorial(QObject):
+ xChanged = Signal(int)
+ def __init__(self):
+ super(Factorial, self).__init__()
+ self.xval = -1
+ self.facval = 1
+ def getX(self):
+ return self.xval
+ def setX(self, x):
+ if self.xval == x:
+ return
+ self.xval = x
+ self.xChanged.emit(x)
+ x = Property(int, getX, setX)
+ def getFact(self):
+ return self.facval
+ def setFact(self, fac):
+ self.facval = fac
+ fac = Property(int, getFact, setFact)
+
+class FactorialLoopTransition(QSignalTransition):
+ def __init__(self, fact):
+ super(FactorialLoopTransition, self).__init__(fact, SIGNAL('xChanged(int)'))
+ self.fact = fact
+ def eventTest(self, e):
+ if not super(FactorialLoopTransition, self).eventTest(e):
+ return False
+ return e.arguments()[0] > 1
+ def onTransition(self, e):
+ x = e.arguments()[0]
+ fac = self.fact.fac
+ self.fact.fac = x * fac
+ self.fact.x = x - 1
+
+class FactorialDoneTransition(QSignalTransition):
+ def __init__(self, fact):
+ super(FactorialDoneTransition, self).__init__(fact, SIGNAL('xChanged(int)'))
+ self.fact = fact
+ def eventTest(self, e):
+ if not super(FactorialDoneTransition, self).eventTest(e):
+ return False
+ return e.arguments()[0] <= 1
+ def onTransition(self, e):
+ print(self.fact.fac)
+
+if __name__ == '__main__':
+ import sys
+ app = QCoreApplication(sys.argv)
+ factorial = Factorial()
+ machine = QStateMachine()
+
+ compute = QState(machine)
+ compute.assignProperty(factorial, 'fac', 1)
+ compute.assignProperty(factorial, 'x', 6)
+ compute.addTransition(FactorialLoopTransition(factorial))
+
+ done = QFinalState(machine)
+ doneTransition = FactorialDoneTransition(factorial)
+ doneTransition.setTargetState(done)
+ compute.addTransition(doneTransition)
+
+ machine.setInitialState(compute)
+ machine.finished.connect(app.quit)
+ machine.start()
+
+ sys.exit(app.exec_())
diff --git a/examples/widgets/state-machine/pingpong.py b/examples/widgets/state-machine/pingpong.py
new file mode 100755
index 000000000..f0233ffc0
--- /dev/null
+++ b/examples/widgets/state-machine/pingpong.py
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com>
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples 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 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$
+##
+#############################################################################
+
+from PySide2.QtWidgets import *
+from PySide2.QtCore import *
+
+class PingEvent(QEvent):
+ def __init__(self):
+ super(PingEvent, self).__init__(QEvent.Type(QEvent.User+2))
+class PongEvent(QEvent):
+ def __init__(self):
+ super(PongEvent, self).__init__(QEvent.Type(QEvent.User+3))
+
+class Pinger(QState):
+ def __init__(self, parent):
+ super(Pinger, self).__init__(parent)
+ def onEntry(self, e):
+ self.p = PingEvent()
+ self.machine().postEvent(self.p)
+ print('ping?')
+
+class PongTransition(QAbstractTransition):
+ def eventTest(self, e):
+ return e.type() == QEvent.User+3
+ def onTransition(self, e):
+ self.p = PingEvent()
+ machine.postDelayedEvent(self.p, 500)
+ print('ping?')
+class PingTransition(QAbstractTransition):
+ def eventTest(self, e):
+ return e.type() == QEvent.User+2
+ def onTransition(self, e):
+ self.p = PongEvent()
+ machine.postDelayedEvent(self.p, 500)
+ print('pong!')
+
+if __name__ == '__main__':
+ import sys
+ app = QCoreApplication(sys.argv)
+
+ machine = QStateMachine()
+ group = QState(QState.ParallelStates)
+ group.setObjectName('group')
+
+ pinger = Pinger(group)
+ pinger.setObjectName('pinger')
+ pinger.addTransition(PongTransition())
+
+ ponger = QState(group)
+ ponger.setObjectName('ponger')
+ ponger.addTransition(PingTransition())
+
+ machine.addState(group)
+ machine.setInitialState(group)
+ machine.start()
+
+ sys.exit(app.exec_())
diff --git a/examples/widgets/state-machine/rogue.py b/examples/widgets/state-machine/rogue.py
new file mode 100755
index 000000000..e6ab3faef
--- /dev/null
+++ b/examples/widgets/state-machine/rogue.py
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com>
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples 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 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$
+##
+#############################################################################
+
+from PySide2.QtWidgets import *
+from PySide2.QtGui import *
+from PySide2.QtCore import *
+
+class MovementTransition(QEventTransition):
+ def __init__(self, window):
+ super(MovementTransition, self).__init__(window, QEvent.KeyPress)
+ self.window = window
+ def eventTest(self, event):
+ if event.type() == QEvent.StateMachineWrapped and \
+ event.event().type() == QEvent.KeyPress:
+ key = event.event().key()
+ return key == Qt.Key_2 or key == Qt.Key_8 or \
+ key == Qt.Key_6 or key == Qt.Key_4
+ return False
+ def onTransition(self, event):
+ key = event.event().key()
+ if key == Qt.Key_4:
+ self.window.movePlayer(self.window.Left)
+ if key == Qt.Key_8:
+ self.window.movePlayer(self.window.Up)
+ if key == Qt.Key_6:
+ self.window.movePlayer(self.window.Right)
+ if key == Qt.Key_2:
+ self.window.movePlayer(self.window.Down)
+
+class Custom(QState):
+ def __init__(self, parent, mw):
+ super(Custom, self).__init__(parent)
+ self.mw = mw
+
+ def onEntry(self, e):
+ print(self.mw.status)
+
+class MainWindow(QMainWindow):
+ def __init__(self):
+ super(MainWindow, self).__init__()
+ self.pX = 5
+ self.pY = 5
+ self.width = 35
+ self.height = 20
+ self.statusStr = ''
+
+ database = QFontDatabase()
+ font = QFont()
+ if 'Monospace' in database.families():
+ font = QFont('Monospace', 12)
+ else:
+ for family in database.families():
+ if database.isFixedPitch(family):
+ font = QFont(family, 12)
+ self.setFont(font)
+
+ self.setupMap()
+ self.buildMachine()
+ self.show()
+ def setupMap(self):
+ self.map = []
+ qsrand(QTime(0, 0, 0).secsTo(QTime.currentTime()))
+ for x in range(self.width):
+ column = []
+ for y in range(self.height):
+ if x == 0 or x == self.width - 1 or y == 0 or \
+ y == self.height - 1 or qrand() % 40 == 0:
+ column.append('#')
+ else:
+ column.append('.')
+ self.map.append(column)
+
+ def buildMachine(self):
+ machine = QStateMachine(self)
+
+ inputState = Custom(machine, self)
+ # this line sets the status
+ self.status = 'hello!'
+ # however this line does not
+ inputState.assignProperty(self, 'status', 'Move the rogue with 2, 4, 6, and 8')
+
+ machine.setInitialState(inputState)
+ machine.start()
+
+ transition = MovementTransition(self)
+ inputState.addTransition(transition)
+
+ quitState = QState(machine)
+ quitState.assignProperty(self, 'status', 'Really quit(y/n)?')
+
+ yesTransition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_Y)
+ self.finalState = QFinalState(machine)
+ yesTransition.setTargetState(self.finalState)
+ quitState.addTransition(yesTransition)
+
+ noTransition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_N)
+ noTransition.setTargetState(inputState)
+ quitState.addTransition(noTransition)
+
+ quitTransition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_Q)
+ quitTransition.setTargetState(quitState)
+ inputState.addTransition(quitTransition)
+
+ machine.setInitialState(inputState)
+ machine.finished.connect(qApp.quit)
+ machine.start()
+
+ def sizeHint(self):
+ metrics = QFontMetrics(self.font())
+ return QSize(metrics.width('X') * self.width, metrics.height() * (self.height + 1))
+ def paintEvent(self, event):
+ metrics = QFontMetrics(self.font())
+ painter = QPainter(self)
+ fontHeight = metrics.height()
+ fontWidth = metrics.width('X')
+
+ painter.fillRect(self.rect(), Qt.black)
+ painter.setPen(Qt.white)
+
+ yPos = fontHeight
+ painter.drawText(QPoint(0, yPos), self.status)
+ for y in range(self.height):
+ yPos += fontHeight
+ xPos = 0
+ for x in range(self.width):
+ if y == self.pY and x == self.pX:
+ xPos += fontWidth
+ continue
+ painter.drawText(QPoint(xPos, yPos), self.map[x][y])
+ xPos += fontWidth
+ painter.drawText(QPoint(self.pX * fontWidth, (self.pY + 2) * fontHeight), '@')
+ def movePlayer(self, direction):
+ if direction == self.Left:
+ if self.map[self.pX - 1][self.pY] != '#':
+ self.pX -= 1
+ elif direction == self.Right:
+ if self.map[self.pX + 1][self.pY] != '#':
+ self.pX += 1
+ elif direction == self.Up:
+ if self.map[self.pX][self.pY - 1] != '#':
+ self.pY -= 1
+ elif direction == self.Down:
+ if self.map[self.pX][self.pY + 1] != '#':
+ self.pY += 1
+ self.repaint()
+ def getStatus(self):
+ return self.statusStr
+ def setStatus(self, status):
+ self.statusStr = status
+ self.repaint()
+ status = Property(str, getStatus, setStatus)
+ Up = 0
+ Down = 1
+ Left = 2
+ Right = 3
+ Width = 35
+ Height = 20
+
+if __name__ == '__main__':
+ import sys
+ app = QApplication(sys.argv)
+ mainWin = MainWindow()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/state-machine/trafficlight.py b/examples/widgets/state-machine/trafficlight.py
new file mode 100755
index 000000000..8e1d71d94
--- /dev/null
+++ b/examples/widgets/state-machine/trafficlight.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com>
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples 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 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$
+##
+#############################################################################
+
+from PySide2.QtWidgets import *
+from PySide2.QtGui import *
+from PySide2.QtCore import *
+
+class LightWidget(QWidget):
+ def __init__(self, color):
+ super(LightWidget, self).__init__()
+ self.color = color
+ self.onVal = False
+ def isOn(self):
+ return self.onVal
+ def setOn(self, on):
+ if self.onVal == on:
+ return
+ self.onVal = on
+ self.update()
+ @Slot()
+ def turnOff(self):
+ self.setOn(False)
+ @Slot()
+ def turnOn(self):
+ self.setOn(True)
+ def paintEvent(self, e):
+ if not self.onVal:
+ return
+ painter = QPainter(self)
+ painter.setRenderHint(QPainter.Antialiasing)
+ painter.setBrush(self.color)
+ painter.drawEllipse(0, 0, self.width(), self.height())
+
+ on = Property(bool, isOn, setOn)
+
+class TrafficLightWidget(QWidget):
+ def __init__(self):
+ super(TrafficLightWidget, self).__init__()
+ vbox = QVBoxLayout(self)
+ self.redLight = LightWidget(Qt.red)
+ vbox.addWidget(self.redLight)
+ self.yellowLight = LightWidget(Qt.yellow)
+ vbox.addWidget(self.yellowLight)
+ self.greenLight = LightWidget(Qt.green)
+ vbox.addWidget(self.greenLight)
+ pal = QPalette()
+ pal.setColor(QPalette.Background, Qt.black)
+ self.setPalette(pal)
+ self.setAutoFillBackground(True)
+
+def createLightState(light, duration, parent=None):
+ lightState = QState(parent)
+ timer = QTimer(lightState)
+ timer.setInterval(duration)
+ timer.setSingleShot(True)
+ timing = QState(lightState)
+ timing.entered.connect(light.turnOn)
+ timing.entered.connect(timer.start)
+ timing.exited.connect(light.turnOff)
+ done = QFinalState(lightState)
+ timing.addTransition(timer, SIGNAL('timeout()'), done)
+ lightState.setInitialState(timing)
+ return lightState
+
+class TrafficLight(QWidget):
+ def __init__(self):
+ super(TrafficLight, self).__init__()
+ vbox = QVBoxLayout(self)
+ widget = TrafficLightWidget()
+ vbox.addWidget(widget)
+ vbox.setContentsMargins(0, 0, 0, 0)
+
+ machine = QStateMachine(self)
+ redGoingYellow = createLightState(widget.redLight, 1000)
+ redGoingYellow.setObjectName('redGoingYellow')
+ yellowGoingGreen = createLightState(widget.redLight, 1000)
+ yellowGoingGreen.setObjectName('redGoingYellow')
+ redGoingYellow.addTransition(redGoingYellow, SIGNAL('finished()'), yellowGoingGreen)
+ greenGoingYellow = createLightState(widget.yellowLight, 3000)
+ greenGoingYellow.setObjectName('redGoingYellow')
+ yellowGoingGreen.addTransition(yellowGoingGreen, SIGNAL('finished()'), greenGoingYellow)
+ yellowGoingRed = createLightState(widget.greenLight, 1000)
+ yellowGoingRed.setObjectName('redGoingYellow')
+ greenGoingYellow.addTransition(greenGoingYellow, SIGNAL('finished()'), yellowGoingRed)
+ yellowGoingRed.addTransition(yellowGoingRed, SIGNAL('finished()'), redGoingYellow)
+
+ machine.addState(redGoingYellow)
+ machine.addState(yellowGoingGreen)
+ machine.addState(greenGoingYellow)
+ machine.addState(yellowGoingRed)
+ machine.setInitialState(redGoingYellow)
+ machine.start()
+
+if __name__ == '__main__':
+ import sys
+ app = QApplication(sys.argv)
+ widget = TrafficLight()
+ widget.resize(110, 300)
+ widget.show()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/state-machine/twowaybutton.py b/examples/widgets/state-machine/twowaybutton.py
new file mode 100755
index 000000000..6b27787b5
--- /dev/null
+++ b/examples/widgets/state-machine/twowaybutton.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com>
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples 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 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$
+##
+#############################################################################
+
+from PySide2.QtWidgets import *
+from PySide2.QtCore import *
+
+if __name__ == '__main__':
+ import sys
+ app = QApplication(sys.argv)
+ button = QPushButton()
+ machine = QStateMachine()
+
+ off = QState()
+ off.assignProperty(button, 'text', 'Off')
+ off.setObjectName('off')
+
+ on = QState()
+ on.setObjectName('on')
+ on.assignProperty(button, 'text', 'On')
+
+ off.addTransition(button, SIGNAL('clicked()'), on)
+ # Let's use the new style signals just for the kicks.
+ on.addTransition(button.clicked, off)
+
+ machine.addState(off)
+ machine.addState(on)
+ machine.setInitialState(off)
+ machine.start()
+ button.resize(100, 50)
+ button.show()
+ sys.exit(app.exec_())