PySide6 Signal - QtQuick Slot Using QObject.findChild()
In the Qt Widgets examples we’ve seen that a signal is emitted when an event occurs, that a slot is typically a Python method, and that you need to connect them for the mechanism to work. In a hybrid Pyside6/QtQuick application both PySide6 and Qml objects can emit signals, slots can be defined in both Python and Qml files and connections between them can be established either in Python or in Qml. This complicates things a bit but let’s start with a simple example. To use the signals and slots mechanism in a QtQuick application
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
ApplicationWindow {
visible: true
width: 400
height:200
title: "Template App"
RowLayout {
anchors.fill: parent
Label {
id: label
objectName: "label"
text: "Hello Qml!"
Layout.fillWidth: true
Layout.fillHeight: true
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
font.pointSize:24
font.bold: true
color: "steelblue"
// 1. Add a slot function to the label
function updateText () {
label.text = "Timeout event\n"
+ Qt.formatTime(new Date, "hh:mm:ss")
}
}
}
}
- Add a function to a Qml object. In the example we start with the template Qml file and add a JavaScript function to the label. Qml comes with a JavaScript engine that lets you manipulate Qml objects and our function simply sets the label’s text to the current time when executed. Note that we also set two label’s properties:
id
andobjectName
. Theid
property is used to refer to an object from JavaScript code (as inlabel.text = ...
). TheobjectName
property setsQObject.objectName
to the given string which is useful when you need to find the object usingQObject
’sfindChild()
orfindChildren()
methods. Note also thatid
is not a string.
In the Python file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import sys
from PySide6.QtCore import QObject, QTimer
from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine
if __name__ == '__main__':
app = QGuiApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.quit.connect(app.quit)
engine.load('01_rootobjects_findchild.qml')
# 1. Find the Label element
root = engine.rootObjects()[0]
label = root.findChild(QObject, 'label')
# 2. Create a timer and connect
# the timer signal to the label slot
timer = QTimer()
timer.timeout.connect(label.updateText)
timer.start(1000)
result = app.exec()
del engine
sys.exit(result)
-
Get a reference to the Qml Label. Get the root Qml objects using
QQmlApplicationEngine.rootObjects()
-rootObjects()
returns a list andApplicationWindow
is the first (and the only) element in it. AsApplicationWindow
is ultimately aQObject
we useQObject.findChild()
to find the label. -
Create a
QTimer
instance and connect the timer’stimeout
signal to the label’supdateText
slot just as you would in a Qt Widgets application. Finally start the timer and the application itself.
That’s it - every time the timer ticks updateText
is executed and the label’s text is updated. To recap, we have
- a JavaScript function
- a PySide6 signal
- the connection is created in PySide6 code