从 Python 发送信号到 Compononent.onCompleted

Send signal from Python to Compononent.onCompleted

我正在把事情串起来,慢慢开始变得更有意义了。我了解如何使用 onClick 发送信号等。

目的:GUI,根据点击的按钮,它会读取和 RFID 卡。此代码将被保留并传递到数据库。

有两个按钮。一个是开放的,另一个是关闭的。其中任何一个都会打开相同的 RFID Python 脚本来读取卡片。这些脚本都运行在一个stackView中。下面是卡片 reader 的 stackView 页面。它从上一个屏幕上按下的按钮加载得很好。

要导航到正确的 stackView,stackView.push(Qt.resolvedUrl("**GET URL FROM PYTHON**"))

因此,根据上一页按下的按钮,它将加载 Welcome QML 或 goodbye QML

主要 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
    }
}

所以最大的问题是。如何从 Python 中获取 URL 并将其输入 Qt.resolvedurl?

据我了解,OP 希望从 python 处理 StackView url,因此一个可能的解决方案是创建一个 qproperty,将 url 通过连接:

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
    }

}