How to emit Signal from nested QML page to python

问题描述 投票:0回答:3

在我的 QML/python 应用程序中,我可以从 main.qml 向 python 代码发出信号。但是现在在 main.qml 中,我添加了 StackLayout 以加载另一个 page1.qml。在那个 page1.qml 是按钮,现在我想从这个按钮向 python 发出信号。

我使用此方法从 main.qml 文件向 python 发出信号: 但不知道如何从嵌套的 page1.qml

发出它

main.py

from PySide2.QtCore import QObject, QUrl, Slot, Signal, Qt
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine

class Foo(QObject):
    @Slot(str)
    def test_slot(self, input_string : str):
        print(input_string)

if __name__ == "__main__":
    import os
    import sys

    app = QGuiApplication()
    foo = Foo()
    engine = QQmlApplicationEngine()
    
    #CHANGES: line excluded engine.rootContext().setContextProperty("foo", foo)
    
    qml_file = "main.qml"
    current_dir = os.path.dirname(os.path.realpath(__file__))
    filename = os.path.join(current_dir, qml_file)
    engine.load(QUrl.fromLocalFile(filename))
    if not engine.rootObjects():
        sys.exit(-1)
    
    #CHANGES: connect QML signal to Python slot
    engine.rootObjects()[0].test_signal.connect(foo.test_slot, type=Qt.ConnectionType.QueuedConnection)
    
    sys.exit(app.exec_())

main.qml

import QtQuick 2.13
import QtQuick.Controls 2.13

ApplicationWindow {
    visible: true
    
    //CHANGES: declare signal
    signal test_signal(string input_string)

    Button {
        anchors.centerIn: parent
        text: "Example"

        //CHANGES: emit signal
        onClicked: test_signal("Test string")
    }
}

https://stackoverflow.com/a/69595659/5166312

非常感谢。

python qt qml qtquick2
3个回答
1
投票
  1. 为嵌套页面添加
    objectName
    字符串属性(如果它们在单独的文件中,则包括大小写):
    objectName: "page1_objname"
    
  2. 从 Python(或 C++)后端访问嵌套页面
    qmlpage1 = engine.rootObjects()[0].findChild(QObject, "page1_objname")
    
  3. 像往常一样在 Python 或 C++ 后端连接插槽和信号(您的问题或我的回答中已经有代码https://stackoverflow.com/a/69595659/5166312)。
    qmlpage1.page1_signal.connect(
       test_object.test_slot3,
       type=Qt.ConnectionType.QueuedConnection)
    

我在 https://github.com/Ornstein89/pyside6-qml-slotsignal 上的测试示例中包含 StackLayout、两个嵌套页面、3 个信号和 3 个插槽的整个项目

main.py

# This Python file uses the following encoding: utf-8
import sys
from pathlib import Path

from PySide6.QtCore import QObject, QUrl, Slot, Signal, Qt
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine

class TestClass(QObject):
    '''
    Object - slot-owner and signal-acceptor
    '''
    @Slot(str)
    def test_slot1(self, input_string : str):
        print(input_string)
    @Slot(str)
    def test_slot2(self, input_string : str):
        print(input_string)
    @Slot(str)
    def test_slot3(self, input_string : str):
        print(input_string)

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    test_object = TestClass()
    qml_file = Path(__file__).resolve().parent / "main.qml"
    engine.load(qml_file)
    if not engine.rootObjects():
        sys.exit(-1)

    # !!! connect ApplicationWindow.mainapp_signal() to test_object.test_slot1
    engine.rootObjects()[0]\
        .mainapp_signal.connect(
            test_object.test_slot1,
            type=Qt.ConnectionType.QueuedConnection)

    # !!! access nested page1 from python backend
    qmlpage1 = engine.rootObjects()[0].findChild(QObject, "page1_objname")

    # !!! and connect MyPage1.page1_signal() to test_object.test_slot2
    qmlpage1.page1_signal.connect(
            test_object.test_slot2,
            type=Qt.ConnectionType.QueuedConnection)

    # !!! access nested page2 from python backend
    qmlpage2 = engine.rootObjects()[0].findChild(QObject, "page2_objname")

    # !!! and connect MyPage2.page2_signal() to test_object.test_slot3
    qmlpage2.page2_signal.connect(
            test_object.test_slot3,
            type=Qt.ConnectionType.QueuedConnection)

    sys.exit(app.exec())

main.qml

import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts

ApplicationWindow {
    width: 480
    height: 640
    visible: true
    title: qsTr("Example for Stackoverflow")

    // !!! singal №1 in root QML Object - most easy to connect in main.py
    signal mainapp_signal(string input_string)

    StackLayout {
        id : stacklayout
        anchors.fill: parent
        MyPage1 {
            id: page1
        }
        MyPage2 {
            id: page2
        }
    }
}

MyPage1.qml

import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts

Page{
    id: page1

    // !!! singal №2 in nested QML Object
    signal page1_signal(string input_string)

    // !!! important - this name is used
    // to access page1 from C++ or Python backend
    objectName: "page1_objname"

    Button{
        text: "Go to page 2"
        anchors.centerIn: parent
        onClicked: {
            stacklayout.currentIndex = 1
            // call root object signal from nested object
            mainapp_signal("mainapp_signal() from page1");
            // call nested object signal from same object
            page1_signal("page1_signal() from page1");
            // call another nested object signal
            page2.page2_signal("page2_signal() from page1");
        }
    }
}

MyPage2.qml

import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts

Page{
    id: page2

    // !!! singal №3 in nested QML Object
    signal page2_signal(string input_string)

    // !!! important - this name is used
    // to access page2 from C++ or Python backend
    objectName: "page2_objname"

    Button{
        text: "Go to page 1"
        anchors.centerIn: parent
        onClicked: {
            stacklayout.currentIndex = 0
        }
    }
}

0
投票

您可以添加一个

Conections
元素来使用加载组件的信号。
在此处查看文档.

此外,您可以为您的

page1.qml
项目声明一个组件并使用
sourceComponent
Loader
属性。通过这种方式,您可以在组件内部使用信号来调用外部方法。在此处查看文档.


0
投票

我是新手,想做一个简单的应用。我遵循了您的代码,一切都对我有用。但我无法弄清楚如何获得价值 - (input_string)。继续节目。

你能帮帮我吗?

谢谢

My Problem

© www.soinside.com 2019 - 2024. All rights reserved.