Communication between python and qml



  • Hello, I just started with python and qml and if have a problem with the communication between the qml and the py. In the following function in my python main app class only the first line works

        def foo(self, aword):
            print('from qml: %s was received' % (aword))
            o = self.win.findChild(QObject, 'lbl1')
            print("child: ", o)
            return 'a message from python'
    

    I receive the text sent from the qml, but "self.win.findChild" returns None, and in the qml, the text sent by python is undefined

    Here is the py file

    # -*- coding: utf-8 -*-
    import sys
    import images_rc
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtQml import QQmlApplicationEngine
    from PyQt5.QtCore import QObject, pyqtSlot, QVariant
    
    class MainApp(QObject):
    
        def __init__(self, context, parent=None):
            super(MainApp, self).__init__(parent)
            self.win = parent
            self.ctx = context
    
        @pyqtSlot(QVariant)
        def foo(self, aword):
            print('from qml: %s was received' % (aword))
            o = self.win.findChild(QObject, 'lbl1')
            print("child: ", o)
            return 'a message from python'
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        engine = QQmlApplicationEngine()
        ctx = engine.rootContext()
        engine.load('test.qml')
        win = engine.rootObjects()[0]
        py_mainapp = MainApp(ctx, win)
        ctx.setContextProperty("py_mainapp", py_mainapp)
        win.show()
        sys.exit(app.exec_())
    
    

    Here is the qml file

    import QtQuick 2.9
    import QtQuick.Controls 1.4
    
    Window {
        title: "Test"
        width: 400
        height: 300
    
        Label {
            id: lbl1
        }
    
        Label {
            id: lbl2
        }
    
        Button {
            text: 'pressme'
            onClicked: {
                lbl2.text = py_mainapp.foo('hello from qml')
            }
        }
    }
    

    Does anyone knows what am I doing wrong?

    Here are the logs:

    file:///Users/fabrice/Svn/qt/nasmediasPY/test.qml:20: Error: Cannot assign [undefined] to QString
    from qml: Hello from qml was received
    child: None



  • @le-fab.

    o = self.win.findChild(QObject, 'lbl1')

    I know nothing about QML. But as per http://doc.qt.io/qt-5/qobject.html#findChild, isn't the first parameter supposed to be a string of the name of the object?? Is your findChild() function a special PyQt one?



  • I guess it's some kind of binding, but I'm not sure. I'm going to try to remove the first parameter and test
    with self.win.findChild('lbl1'), Thanks for the advice



  • I confirm self.win.findChild needs the QObject first parameter





  • Thanks for the links.
    self.win.findChild works, with the attribute objectName defined in the qml
    Know I have to find why the text sent from python isn't received in the qml

    If it can help here is the code to access a qml child's property:

    @pyqtSlot(QVariant)
        def foo(self, aword):
                print('from qml: %s was received' % (aword))
                o = self.win.findChild(QObject, 'pyLbl1')
                print('text from label', o.property("text"))
                return 'a message from python'
    


  • @le-fab.
    This is all way beyond my ken! But is it to do with either pyqtProperty or toPyObject? See http://pyqt.sourceforge.net/Docs/PyQt5/qt_properties.html, and https://wiki.python.org/moin/PyQt/Binding widget properties to Python variables where code claims:

    return type(self.findChild(QObject, objectName).property(propertyName).toPyObject())

    ? :)



  • I was reading something close to the solution you pointed: https://riverbankcomputing.com/pipermail/pyqt/2017-January/038497.html
    I guess i'm going to use this kind of implementation to populate the qml.

    I guess we can mark this post as solved because even if I can't read the string in the qml from my foo method, I know how to access and edit the qml child's properties with the win.findChild and the QObject.setProperty methods

    Thanks for the help

    Here is my final test code where everything is working:
    main.py:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    import sys
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtQml import QQmlApplicationEngine
    from PyQt5.QtCore import QObject, pyqtSlot, QVariant
    
    class MainApp(QObject):
    
        def __init__(self, context, parent=None):
            super(MainApp, self).__init__(parent)
            self.win = parent
            self.ctx = context
    
        @pyqtSlot(QVariant)
        def foo(self, aword):
                print('from qml: %s was received' % (aword))
                o = self.win.findChild(QObject, 'pyLbl1')
                print('text from label', o.property("text"))
                o = self.win.findChild(QObject, 'pyLbl2')
                o.setProperty("text", "some text from python")
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        engine = QQmlApplicationEngine()
        ctx = engine.rootContext()
        engine.load('test.qml')
        win = engine.rootObjects()[0]
        py_mainapp = MainApp(ctx, win)
        ctx.setContextProperty("py_mainapp", py_mainapp)
        win.show()
        sys.exit(app.exec_())
    
    

    test.qml:

    import QtQuick 2.4
    import QtQuick.Controls 1.4
    
    ApplicationWindow {
        title: "Test"
        width: 400
        height: 300
    
        Column {
            anchors.fill: parent
            spacing: 10
    
            Label {
                id: lbl1
                objectName: 'pyLbl1'
                text: "text in qml"
            }
    
            Label {
                id: lbl2
                objectName: 'pyLbl2'
                text: "unset"
            }
    
    
            Button {
                text: 'pressme'
                onClicked: {
                    py_mainapp.foo('Hello from qml')
                }
            }
        }
    
    }
    

    I guess I could have used the same name for id and objectName (the ids aren't used in this example anyway)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.