QQuickWidget: Set context property and catch signal from Qt in QML

43 Views Asked by At

I'm developing an application using PySide6. It uses both QtWidgets and QML (using QQuickWidget). I'm not able to catch the signal emitted from Qt in QML.

Here is a minimal reproducable example of the which I develop for demonstration purpose.

main.py

import sys

from PySide6.QtCore import QObject, Signal
from PySide6.QtWidgets import (
    QApplication,
    QMainWindow,
    QGridLayout,
    QHBoxLayout,
    QVBoxLayout,
    QSizePolicy,
    QLabel,
    QPushButton,
    QLineEdit,
    QSpacerItem,
    QWidget
)
from PySide6.QtQuickWidgets import QQuickWidget

class Message(QObject):
    updated = Signal(str, arguments=['msg'])

    def __init__(self):
        super().__init__()

    def set_message(self, msg):
        print(f'emitting signal with message: {msg}')
        self.updated.emit(msg)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('QQuickWidget Example')

        # create QQuickWidget and set the source
        self.qw = QQuickWidget()
        self.qw.setSource('view.qml')
        self.qw.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
        self.qw.setResizeMode(QQuickWidget.SizeRootObjectToView)

        self.lineedit = QLineEdit()
        self.button = QPushButton('Start')
        self.button.clicked.connect(self.on_button_clicked)

        grid = QGridLayout()
        grid.addWidget(QLabel('Ener: '), 0, 0, 1, 1)
        grid.addWidget(self.lineedit, 0, 1, 1, 1)
        grid.addWidget(self.button, 1, 0, 1, 2)

        vertical_layout = QVBoxLayout()
        vertical_layout.addLayout(grid)
        vertical_layout.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Minimum))

        main_layout = QHBoxLayout()
        main_layout.addLayout(vertical_layout)
        main_layout.addWidget(self.qw)
        main_layout.setStretch(0, 1)

        widget = QWidget()
        widget.setLayout(main_layout)
        self.setCentralWidget(widget)

        self.message = Message()
        # THIS DOESN'T SEEMS TO SET THE PROPERTY IN QML
        self.qw.engine().rootContext().setContextProperty('message', self.message)

    def on_button_clicked(self):
        msg = self.lineedit.text()
        self.message.set_message(msg)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

Here the the view.qml file:

import QtQuick

Rectangle {

    property string newText: "Hello"
    property QtObject message

    id: root
    width: 500
    height: 500
    color: "white"

    Text {
        id: text
        anchors.fill: parent
        text: newText
        font.pixelSize: 24
        color: "blue"
    }

    Connections {
        target: message

        function onUpdated(msg) {
            newText = msg
            console.log(msg)
        }
    }
}

Upon clicking the button, the text in the QLineEdit is emitted in the signal which I'm trying to catch in QML but the text in the QML is not getting updated.

Can someone please point me what is wrong with the code.

enter image description here

0

There are 0 best solutions below