Qml Signal - PySide6 Slot Using QmlElement

In this example we have a Qml signal, a PySide6 slot and we connect them in our Qml code. To do that

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
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

// 2. Import the class

import examples.logger


ApplicationWindow {

    visible: true
    width: 400
    height:200
    title: "Template App"
    
    Logger {
        id: logger
    }

    RowLayout {
        
        anchors.fill: parent
        
        Button {
        
            Layout.fillWidth: true
            Layout.fillHeight: true
            
            text: "Click Me!"
            
            // 3. Connect Qml Button.clicked signal 
            //    to Logger.log slot
            
            onClicked: {
                logger.log("You clicked me!")
            }
        }
    }
}
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
import sys

from PySide6.QtGui import QGuiApplication
from PySide6.QtQml import QQmlApplicationEngine, QmlElement

from PySide6.QtCore import QObject, Slot


# 1. Create a class that can be imported into Qml

QML_IMPORT_NAME = 'examples.logger'
QML_IMPORT_MAJOR_VERSION = 1


@QmlElement
class Logger(QObject):
    
    @Slot(str)
    def log(self, message):
        print(message)


if __name__ == '__main__':

    app = QGuiApplication(sys.argv)
    
    engine = QQmlApplicationEngine()
    engine.quit.connect(app.quit)
    engine.load('03_qmlelement.qml')

    result = app.exec()
    del engine
    
    sys.exit(result)
  1. Create a Python class with a slot method and register it with the Qml type sistem so it can be used from within Qml. The class needs to be derived from QObject and you need to decorate it with the @QmlElement decorator. Remember how using the @Slot decorator was recommended but not mandatory in Qt Widget applications? Here you have to decorate your slot method with @Slot or the Qml engine will say TypeError: Property 'log' of object Logger(0x1884cdefae0) is not a function. Lastly, you need to set two global variables: QML_IMPORT_NAME to hold the name by which your class will be referred in Qml, and QML_IMPORT_MAJOR_VERSION which is usually set to 1. The PySide6 documentation on the two is a bit sparse but if you omit them PySide6 will say TypeError: You need specify QML_IMPORT_NAME in order to use QmlElement.. The two variables are also listed as qmake variable names but also very briefly.

  2. Import the Logger class using the name specified in QML_IMPORT_NAME (in the example import examples.logger), add a Logger instance to the application assigning it an id, in this case logger.

  3. Connect the Qml Button.clicked signal to the PySide6 slot. The clicked signal matching event handler is named onClicked and you just call the PySide6 slot from within it.