Search code examples
pythonqmlpyside2

Unable to connect to signal in QML emitted from Python


I have a QQuickItem class created in Python:

class MyPage(QQuickItem):
    def __init__(self, parent=None) -> None:
        super().__init__(parent)
        error_encountered = Signal(str)

    @QtCore.Slot(QUrl, result=None)
    def load_report(self, file_path: QUrl) -> None:
        print(f"Called with: {file_path}")
        self.error_encountered.emit("Uh oh!")

The above class is registered as:

qmlRegisterType(MyPage, "MyPage", 1, 0, "MyPage")

My QML looks like:

MyPage {
    signal errorEncountered(string text)
    Component.onCompleted: error_encountered.connect(errorEncountered)
    onErrorEncountered: console.log(text)
}

However, I get the following error:

qrc:/qml/main.qml:93: ReferenceError: error_encountered is not defined

The pattern for PySide2 to connect to signals from QML to the source code is a bit different in Python than C++ and I'm having trouble figuring it out. In C++ I would have had a signal defined like void errorEncountered(const QString& errorMessage); and in my QML I could have simply done onErrorEncountered: console.log(errorMessage).


Solution

  • The signals are declared as an attribute of the class, that is, they should not be created in any method of the class. The solution is:

    class MyPage(QQuickItem):
        error_encountered = Signal(str) # <---
    
        def __init__(self, parent=None) -> None:
            super().__init__(parent)
    
        @QtCore.Slot(QUrl, result=None)
        def load_report(self, file_path: QUrl) -> None:
            print(f"Called with: {file_path}")
            self.error_encountered.emit("Uh oh!")