Reputation: 7504
Trying to learn PyQt5 QStateMachine
with transitions derived from QSignalTransition
following this example written for PySide. To use PyQt I just changed the definition of the signal, and the way it is referenced in QSignalTransition
initializer. This is the complete code:
from PyQt5.QtCore import QObject, pyqtSignal, QSignalTransition, QCoreApplication, QStateMachine, QState, QFinalState
class Factorial(QObject):
xChanged = pyqtSignal(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.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.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_())
This state machine just compute the factorial of 6 and print it.
My problem is, in both transitions, this piece of code:
def eventTest(self, e):
if not super(FactorialDoneTransition, self).eventTest(e):
return False
return e.arguments()[0] <= 1
returns False
on the first and only call. I assume this is because the event passed is not of the proper type, and the superclass returns False
. With this behavior the transitions are never executed, and the the state machine remains at its initial state.
Can someone explain what is the problem? Is it my conversion from PySide to PyQt which is wrong?
Upvotes: 1
Views: 343
Reputation: 243955
The assignProperty()
method expects a Q_PROPERTY that in the case of PySide/PySide2 equals Property (which is different from the property provided by python natively) and in the case of PyQt4/PyQt5 you must use pyqtProperty, and that is the cause of the error so the solution is to replace with the following:
from PyQt5.QtCore import QObject, pyqtSignal, QSignalTransition, QCoreApplication, QStateMachine, QState, QFinalState, pyqtProperty
class Factorial(QObject):
xChanged = pyqtSignal(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 = pyqtProperty(int, getX, setX) # <---
def getFact(self):
return self.facval
def setFact(self, fac):
self.facval = fac
fac = pyqtProperty(int, getFact, setFact) # <---
# ...
Upvotes: 1