Search code examples
pythonqmlpyside2

Send signal from Python to Compononent.onCompleted


I am sort of stringing things together and it is slowly starting to make more sense. I get how to send signals etc. with a onClick.

Aim: GUI where depending on button clicked, it will read, and RFID card. This code will be kept and passed to database.

There are two buttons. One is open, the other is close. Either of these will open same RFID Python script to read the card. These scripts are all run in a stackView. Below is the card reader stackView Page. It loads perfectly fine from the buttons pressed on previous screen.

To navigate to the correct stackView, stackView.push(Qt.resolvedUrl("**GET URL FROM PYTHON**")).

So Depending on the button pressed on the previous page, it will load either Welcome QML or goodbye QML

Main QML

///For button OPEN
onClicked: {
    backend.open() ///Here connect to the correct python def
    stackView.push(Qt.resolvedUrl("ReadCard.qml")) ///Go to read card
}

/// For button CLOSE
onClicked: {
    backend.close() ///Here connect to the correct python def
    stackView.push(Qt.resolvedUrl("ReadCard.qml"))///Go to read card
}

Python: main.py

# Signal Set Data
readOpen = Signal(str)
scanOut = Signal(str)

@Slot()
def open(self):
    # Read card code
    # SQL Code
    # Move to Welcome QML if the lock is opened.
    self.readOpen.emit("Welcome.qml")

@Slot()
def close(self):
    # Read card code
    # SQL Code
    # Move to Good-Bye QML when lock is closed.
    self.scanOut.emit("GoodBye.qml")
    print("This is where the code to clock out will go")  

QML: reader.qml

import QtQuick 2.0
import QtQuick.Controls 2.15
import "../controls"
import QtQuick.Layouts 1.0

Item {
    Rectangle {
        id: rectangle
        ...Other properties...

        Rectangle {
            id: rectangleTop
            ...Other Properties...
        }

        Rectangle {
            id: rectangleVisible
            color: "#1d2128"
            radius: 10
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.top: rectangleTop.bottom
            anchors.bottom: parent.bottom
            anchors.bottomMargin: 40
            anchors.rightMargin: 50
            anchors.leftMargin: 50
            anchors.topMargin: 10

            //The timer just used to simulate card read as no card reader connected yet
            Timer {
                    id: timer
            }

            function delay(delayTime,cb) {
                timer.interval = delayTime;
                timer.repeat = false;
                timer.triggered.connect(cb);
                timer.start();
            }

            Component.onCompleted: delay(1000, function() {
                stackView.push(Qt.resolvedUrl("URL FROM PYTHON"))
            })

            Text {
                id: text1
                x: 148
                y: 119
                width: 288
                height: 109
                color: "#ffffff"
                text: qsTr("Scan your card")
                anchors.verticalCenter: parent.verticalCenter
                font.pixelSize: 36
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
                anchors.horizontalCenter: parent.horizontalCenter
            }
        }
    }

    Connections{
        target: backend
    }
}

So the big question is. How to get that URL from Python and feed it into the Qt.resolvedurl?


Solution

  • From what I understood is that the OP wants the StackView url to be handled from python, so a possible solution is to create a qproperty that places the url through a Connection:

    import os
    import random
    import sys
    from pathlib import Path
    
    from PySide2.QtCore import Property, QCoreApplication, QObject, Qt, QUrl, Signal, Slot
    from PySide2.QtGui import QGuiApplication
    from PySide2.QtQml import QQmlApplicationEngine
    
    CURRENT_DIRECTORY = Path(__file__).resolve().parent
    
    
    class Manager(QObject):
        url_changed = Signal(name="urlChanged")
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self._url = QUrl()
    
        @Property(QUrl, notify=url_changed)
        def url(self):
            return self._url
    
        def _update_url(self, url):
            if self.url == url:
                return
            self._url = url
            self.url_changed.emit()
    
        @Slot()
        def open(self):
            self._update_url(QUrl("Welcome.qml"))
    
        @Slot()
        def close(self):
            self._update_url(QUrl("GoodBye.qml"))
    
    
    def main():
        app = QGuiApplication(sys.argv)
    
        manager = Manager()
    
        engine = QQmlApplicationEngine()
        engine.rootContext().setContextProperty("manager", manager)
    
        filename = os.fspath(CURRENT_DIRECTORY / "main.qml")
        url = QUrl.fromLocalFile(filename)
    
        def handle_object_created(obj, obj_url):
            if obj is None and url == obj_url:
                QCoreApplication.exit(-1)
    
        engine.objectCreated.connect(handle_object_created, Qt.QueuedConnection)
    
        engine.load(url)
    
        sys.exit(app.exec_())
    
    
    if __name__ == "__main__":
        main()
    

    main.qml

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Layouts 1.15
    import QtQuick.Window 2.15
    
    Window {
        width: 640
        height: 480
        visible: true
        title: qsTr("Qt is awesome!!!")
    
        RowLayout {
            id: row_layout
    
            width: parent.width
    
            Button {
                text: "Open"
                Layout.fillWidth: true
                onClicked: manager.open()
            }
    
            Button {
                text: "Close"
                Layout.fillWidth: true
                onClicked: manager.close()
            }
    
        }
    
        StackView {
            id: stack_view
    
            anchors.top: row_layout.bottom
            anchors.bottom: parent.bottom
            width: parent.width
        }
    
        Connections {
            function onUrlChanged() {
                stack_view.pop();
                stack_view.push(Qt.resolvedUrl(manager.url));
            }
    
            target: manager
        }
    
    }
    

    Welcome.qml

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    
    Page {
        Text {
            text: "Welcome"
            anchors.centerIn: parent
        }
    
    }
    

    GoodBye.qml

    import QtQuick 2.15
    import QtQuick.Controls 2.15
    
    Page {
        Text {
            text: "GoodBye"
            anchors.centerIn: parent
        }
    
    }