Hi,

I've been rewriting the state machine examples into Python with the goal of 
uploading them when I'm done.

http://doc.qt.nokia.com/4.7/examples-statemachine.html

However most of them don't work. I've attached them to this email. Only the 
first 2 examples work, the last 4 have problems. Like the ping pong one goes 
through 3 ping<->pongs and then Segmentation Faults. Yet I don't see any 
problem there.

If you take a look at the rogue.py then on line 72, that simple state machine 
fails to set the property.

Some examples like these would be very useful examples for showing usage of 
signal/slots, properties and state machine in PySide.
                                          
from PySide.QtGui import *
from PySide.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_())
from PySide.QtGui import *
from PySide.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_())
from PySide.QtGui import *
from PySide.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_())
from PySide.QtGui import *
from PySide.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:
            window.movePlayer(window.Left)
        if key == Qt.Key_8:
            window.movePlayer(window.Up)
        if key == Qt.Key_6:
            window.movePlayer(window.Right)
        if key == Qt.Key_2:
            window.movePlayer(window.Down)

class Custom(QState):
    def __init__(self, parent, mw):
        self.mw = mw
        super(Custom, self).__init__(parent)
    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()

        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_())
from PySide.QtGui import *
from PySide.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(machine)
        s1.assignProperty(button, 'text', 'Outside')

        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_())
from PySide.QtGui import *
from PySide.QtCore import *

class LightWidget(QWidget):
    def __init__(self, colour):
        super(LightWidget, self).__init__()
        self.colour = colour
        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.colour)
        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.setMargin(0)

        machine = QStateMachine(self)
        redGoingYellow = createLightState(widget.redLight, 3000)
        redGoingYellow.setObjectName('redGoingYellow')
        yellowGoingGreen = createLightState(widget.redLight, 1000)
        yellowGoingGreen.setObjectName('redGoingYellow')
        redGoingYellow.addTransition(redGoingYellow, SIGNAL('finished()'), yellowGoingGreen)
        greenGoingYellow = createLightState(widget.redLight, 3000)
        greenGoingYellow.setObjectName('redGoingYellow')
        yellowGoingGreen.addTransition(yellowGoingGreen, SIGNAL('finished()'), greenGoingYellow)
        yellowGoingRed = createLightState(widget.redLight, 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_())
from PySide.QtGui import *
from PySide.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)
    on.addTransition(button, SIGNAL('clicked()'), off)

    machine.addState(off)
    machine.addState(on)
    machine.setInitialState(off)
    machine.start()
    button.resize(100, 50)
    button.show()
    sys.exit(app.exec_())
_______________________________________________
PySide mailing list
[email protected]
http://lists.openbossa.org/listinfo/pyside

Reply via email to