简体   繁体   English

QSignalTransition 子类从未收到自定义 PyQt 信号

[英]Custom PyQt signal never received by QSignalTransition subclass

Trying to learn PyQt5 QStateMachine with transitions derived from QSignalTransition following this example written for PySide.努力学习PyQt5 QStateMachine与源自过渡QSignalTransition下面这个例子对于PySide写的。 To use PyQt I just changed the definition of the signal, and the way it is referenced in QSignalTransition initializer.为了使用 PyQt,我只是更改了信号的定义,以及在QSignalTransition初始化程序中引用它的方式。 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.这个状态机只是计算 6 的阶乘并打印出来。

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.第一次也是唯一一次调用时返回False I assume this is because the event passed is not of the proper type, and the superclass returns False .我认为这是因为传递的事件类型不正确,并且超类返回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?是我从 PySide 到 PyQt 的转换是错误的吗?

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: 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) # <---

# ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM