0
votes

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?

1

1 Answers

1
votes

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
    }

}