从 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
}
}
我正在把事情串起来,慢慢开始变得更有意义了。我了解如何使用 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
}
}