在为PySide编写的QStateMachine
之后,尝试学习PyQt5 QSignalTransition
与来自this example的转换。要使用PyQt,我只是改变了信号的定义,以及它在QSignalTransition
初始化器中引用的方式。这是完整的代码:
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_())
这个状态机只计算6的阶乘并打印它。
我的问题是,在这两个转换中,这段代码:
def eventTest(self, e):
if not super(FactorialDoneTransition, self).eventTest(e):
return False
return e.arguments()[0] <= 1
在第一次也是唯一一次通话时返回False
。我假设这是因为传递的事件不是正确的类型,超类返回False
。使用此行为,永远不会执行转换,并且状态机保持其初始状态。
有人能解释一下是什么问题吗?是我从PySide到PyQt的转换是错的吗?
assignProperty()
方法需要一个Q_PROPERTY,在PySide / PySide2的情况下等于Property(与python本身提供的属性不同),在PyQt4 / PyQt5的情况下你必须使用pyqtProperty,这就是错误的原因所以解决方案是替换为以下内容:
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) # <---
# ...