in my QML/python app I can emit signal from main.qml to the python code. But now In main.qml I added StackLayout for loading another page1.qml. In that page1.qml is button, now I want to emit signal from this button to the python.
I use this method for emit signals from main.qml file to the python: But do not know how to emit it from nested 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
Thank you very much.
CodePudding user response:
- Add
objectName
string property for nested pages (included the case if they are in separate files):objectName: "page1_objname"
- Access nested pages from Python (or C ) backend
qmlpage1 = engine.rootObjects()[0].findChild(QObject, "page1_objname")
- Connect slot and signal as usually in Python or C backend (you already have code in your question or in my answer https://stackoverflow.com/a/69595659/5166312).
qmlpage1.page1_signal.connect( test_object.test_slot3, type=Qt.ConnectionType.QueuedConnection)
The whole project with StackLayout, two nested pages, 3 signals and 3 slots in my test example on https://github.com/Ornstein89/pyside6-qml-slotsignal.
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
}
}
}
CodePudding user response:
You can add a Conections
element to use signals of loaded component.
Look at documentation here.
Also, you can declare a component for your page1.qml
item and use sourceComponent
property of Loader
. In this way you can use signal inside component to call an outer method. Look at documentation here.