Ir para o conteúdo

Python e Qt 6: Como utilizar um arquivo de interface QML com QQmlApplicationEngine()

Como utilizar um arquivo de interface QML com a linguagem de programação Python e QQmlApplicationEngine().

Código

Cuidado

Lembre-se de adequar a localização do arquivo de interface e ícones.

QML

 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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.0

ApplicationWindow {
    id: application_window
    width: 1366/2
    height: 768/2
    visible: true
    title: qsTr("Python e Qt 6: Signals e Slots (QML QQmlApplicationEngine)")
    onClosing: {
        ClassName.closeEvent()
    }

    menuBar: MenuBar {
        id: menu_bar
        Menu {
            id: menu_file
            title: "&Arquivo"
            MenuItem {
                id: menu_item_close_app
                text: "Sair"
                ToolTip.text: "Sair do aplicativo"
                ToolTip.visible: hovered
                icon.source: "../../../data/icons/exit-128px.png"
                onTriggered: Qt.quit()
            }
        }
    }

    ColumnLayout {
        anchors.fill: parent
        anchors.topMargin: 12
        anchors.bottomMargin: 12
        anchors.leftMargin: 12
        anchors.rightMargin: 12
        spacing: 12

        Label {
            id: label
            text: qsTr("Digite algo no campo de texto e clique no botão")
            textFormat: Text.RichText
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
            wrapMode: Text.WordWrap
            Layout.fillHeight: true
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
        }

        TextField {
            id: text_field
            Layout.fillWidth: true
            placeholderText: qsTr("Digite algo")
        }

        Button {
            id: button
            text: "Clique Aqui (ClassName)"
            Layout.fillWidth: true
            // Criando uma variável auxiliar:
            property var text_field_value: ""
            onClicked: {
                text_field_value = text_field.text
                if (text_field_value) {
                    label.text = ClassName.on_button_clicked(text_field_value)
                }
                else {
                    label.text = qsTr("Digite algo no campo de texto!")
                }
            }
        }

        Button {
            id: button_other
            text: "Clique Aqui (OtherClassName)"
            Layout.fillWidth: true
            // Criando uma variável auxiliar:
            property var text_field_value: ""
            onClicked: {
                text_field_value = text_field.text
                if (text_field_value) {
                    label.text = OtherClassName.on_button_clicked(text_field_value)
                }
                else {
                    label.text = qsTr("Digite algo no campo de texto!")
                }
            }
        }
    }
}

Python

 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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# -*- coding: utf-8 -*-
"""Python e Qt 6: Interagir com arquivo de interface QML utilizando
QQmlApplicationEngine().
"""

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


class ClassName(QObject):
    """Métodos e funções criadas na classe podem ser acessadas no arquivo QML."""

    def __init__(self):
        super().__init__()

    # Primeiro valor vem do QML (deve ser definido um tipo).
    # Segundo valor é o retorno que será enviado para o QML
    # (deve ser atribuído um tipo).
    @Slot(str, result=str)
    def on_button_clicked(self, text):
        return f'Texto digitado: <b>{text}</b> (ClassName).'

    def closeEvent(self):
        """Método é executado quando a janela é fechada."""
        print('[!] A janela foi fechada [!]')


class OtherClassName(QObject):
    def __init__(self):
        super().__init__()

    @Slot(str, result=str)
    def on_button_clicked(self, text):
        return f'Texto digitado: <b>{text}</b> (OtherClassName).'


if __name__ == '__main__':
    import sys

    # Para exibir o ícone na taskbar (barra de tarefas) do windows.
    if sys.platform == "win32" or sys.platform == 'win64':
        from ctypes import windll

        appid = 'br.natorsc.exemplo'
        windll.shell32.SetCurrentProcessExplicitAppUserModelID(appid)

    application = QGuiApplication(sys.argv)
    # Ícone da janela.
    application.setWindowIcon(QPixmap('../../../data/icons/icon.png'))

    # Atribuindo a classe a uma variável (obrigatório).
    class_name = ClassName()
    other_class_name = OtherClassName()

    engine = QQmlApplicationEngine()
    # Primeiro valor é o nome que será utilizado no arquivo QML.
    # Segundo valor uma instância da classe que contém os métodos e funções.
    engine.rootContext().setContextProperty('ClassName', class_name)
    # Registrando outra classe para testar.
    engine.rootContext().setContextProperty('OtherClassName', other_class_name)
    engine.load(QUrl.fromLocalFile('ui/MainWindow.qml'))

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(application.exec_())