从 Python 脚本执行 Qml 函数?

Execute a Qml function from Python script?

我正在尝试制作一个脚本,它将根据键盘命令打开一个输入框,您在其中输入一些内容,它会关闭,然后 returns 将文本发送到 python。到目前为止一切正常,在 python 中接受当我的组合键被满足时,我想不出一种方法来显示 Qml gui。我在 C++ 中看到了一些工作示例,但似乎没有找到 python.

main.py

import os
from pathlib import Path
import sys

from PySide6.QtCore import QCoreApplication, Qt, QUrl, QObject, Signal, Slot

from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
from pynput.keyboard import Key, Listener, KeyCode
#is call qml function from python to show window.



CURRENT_DIRECTORY = Path(__file__).resolve().parent
COMBINATION = {Key.shift_r, Key.enter}
current = set()
#KEYBOARD LISTENER
class KeyMonitor(QObject):
    keyPressed = Signal(KeyCode)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.listener = Listener(on_press=self.on_press, on_release=self.on_release)

    def on_press(self, key):
        if key in COMBINATION:
            current.add(key)
            if all(k in current for k in COMBINATION):
                print('All modifiers active!')
                #I WANT TO CALL QML FUNCTION OPEN() RIGHT HERE.

    def on_release(self, key):
        try:
            current.remove(key)
        except KeyError:
            pass

    def stop_monitoring(self):
        self.listener.stop()

    def start_monitoring(self):
        self.listener.start()


#SLOT STUFF
class MainBackend(QObject):
    def __init__(self):
        QObject.__init__(self)

    signalPrintTxtEmitter = Signal(bool)
    @Slot()
    def printTxt(self):
        self.signalPrintTxtEmitter.emit(True)
        print('Hello from Python!')


    input_Text = Signal(str)
    @Slot(str)
    def sendToPython(self, text):
        currentText=text
        print("Python says you typed in:" + " " + currentText)






#RUNNING QML
def main():

    app = QGuiApplication(sys.argv)


    engine = QQmlApplicationEngine()

    main = MainBackend()

    engine.rootContext().setContextProperty("backend", main)

    filename = os.fspath(CURRENT_DIRECTORY / "QML" / "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__":
    monitor = KeyMonitor()
    #monitor.keyPressed.connect(print)
    monitor.start_monitoring()
    main()

main.qml:

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15
import QtQuick.Window 2.15

ApplicationWindow{


    id: root
    title: qsTr("Hello, I'm main.qml!")
    visible: true
    width: 400
    height: 580
    Material.theme: Material.Dark
    Material.accent: Material.LightBlue
    //Component.onCompleted: functions.close()



    TextField {
    id: input_Box
     width: 160
     placeholderText: qsTr("Enter Here")
     anchors.centerIn: parent
     focus: true
     Keys.onPressed: {
        if (event.key == Qt.Key_Return) {
            //backend.printTxt()
            backend.sendToPython(input_Box.text)
            functions.close()
        }              
    }
     
    }


    Button{
        id: button
        focus: true 
        text: qsTr("Click me!")
        onClicked: functions.openQml()
    }



    QtObject {
        id: functions
        function close() {
            root.hide()
        }
        function open() {
            root.show()
        }
    }





    Connections {
        target: backend
        function onSignalPrintTxtEmitter(boolValue){
            return
        }
        function onSignalsendToPythonEmitter(str){
            return
        }

    }
}

与其尝试从 python 调用 QML 函数,不如从 python 发出信号并将 QML 函数调用到关联的插槽:

class KeyMonitor(QObject):
    keyPressed = Signal(KeyCode)
    foo = Signal()

    # ...

    def on_press(self, key):
        if key in COMBINATION:
            current.add(key)
            if all(k in current for k in COMBINATION):
                print("All modifiers active!")
                self.foo.emit()
    main = MainBackend()

    monitor = KeyMonitor()
    QTimer.singleShot(1000, monitor.foo.emit)
    monitor.start_monitoring()

    engine.rootContext().setContextProperty("backend", main)
    engine.rootContext().setContextProperty("monitor", monitor)
    Connections{
        target: monitor
        function onFoo(){
            console.log("Foo")
            functions.open()
        }
    }