Skip to main content
Ir para o conteúdo

Kirigami com o Python

Crie seu primeiro aplicativo Kirigami com PySide

Pré-requisitos

Antes de começar, precisaremos instalar o Kirigami e o PySide em nossa máquina.

logo of Linux operating system ManjaroManjarologo of Linux operating system Arch LinuxArch
sudo pacman -S python-pipx python-pyqt6 pyside6 kirigami flatpak-builder qqc2-desktop-style appstream
logo of Linux operating system openSUSEOpenSUSE
sudo zypper install python3-pipx python3-qt6 python3-pyside6 kf6-kirigami-devel flatpak-builder kf6-qqc2-desktop-style AppStream-compose
logo of Linux operating system FedoraFedora
sudo dnf install pipx python3-pyqt6 python3-pyside6 kf6-kirigami-devel flatpak-builder kf6-qqc2-desktop-style appstream-compose

Se você estiver usando uma distribuição com pacotes PySide6 ou PyQt6 antigos, este tutorial funciona com Construindo software com o distrobox.

Estrutura do projeto

Primeiro, criamos a pasta do nosso projeto (você pode usar os comandos abaixo). Vamos chamá-la de kirigami_python/.

kirigami_python/
├── README.md
├── LICENSE.txt
├── MANIFEST.in                        # Para adicionar nossos arquivos QML
├── pyproject.toml                     # O arquivo principal para gerenciar o projeto
├── org.kde.kirigami_python.desktop
└── src/
    ├── __init__.py                    # Para importar o diretório src/ como um pacote
    ├── __main__.py                    # Para sinalizar o aplicativo como ponto de entrada
    ├── app.py
    └── qml/
        └── Main.qml

O nome do pacote será kirigami_python, o "executável" (script de console) será chamado de kirigami_hello e o ponto de entrada será app.

Para um projeto mais abrangente que aprofunde mais detalhes sobre essa estrutura de arquivo, consulte Projeto completo em Python + Kirigami.

pyproject.toml

Aplicações Python modernas precisam apenas de um único arquivo TOML para especificar todos os metadados, informações de pacotes e dependências, conforme PEP 621. O a seguir serve como um bom ponto de partida para uma aplicação e pode ser estendido posteriormente.

A maior parte do conteúdo deste arquivo é padrão, e uma versão mais completa dele pode ser vista em Python com Kirigami: Estrutura Geral.

 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
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "kirigami_python"
version = "0.1"
authors = [
    {name = "Konqi", email = "konqi@example.com"}
]
classifiers = [
    "Development Status :: 5 - Production/Stable",
    "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
    "Intended Audience :: End Users/Desktop",
    "Topic :: Utilities",
    "Programming Language :: Python",
    "Operating System :: POSIX :: Linux",
]

[project.scripts]
kirigami_hello = "kirigami_python.app:main"

[tool.setuptools]
packages = ["kirigami_python"]
package-dir = {kirigami_python = "src"}
include-package-data = true

[tool.setuptools.data-files]
"share/applications" = ["org.kde.kirigami_python.desktop"]

Observe as linhas destacadas. Conforme mencionado em Estrutura do projeto, o nome do pacote é kirigami_python, o nome do executável é kirigami_hello e o nome do ponto de entrada é app. Em particular, o seguinte deve ser observado:

  • O script do projeto consiste em um script de ponto de entrada que será gerado pelo setuptools para a execução do aplicativo, neste caso kirigami_hello.
  • O script de projeto gerado kirigami_hello executa a função main() no script app.py no pacote kirigami_python.
  • O package-dir padrão para projetos Python geralmente é o diretório raiz. Neste caso, ele é substituído pelo subdiretório src/, agindo como se fosse o diretório raiz do pacote.
  • O package-dir é o motivo pelo qual o script do projeto gerado executa kirigami_python → app em vez de kirigami_python → src → app.
  • O package-dir também é o motivo pelo qual a chamada importlib.resources.files() em app.py executa kirigami_python → qml → Main.qml em vez de kirigami_python → src → qml → Main.qml.

Veja Executando diretamente, como um módulo e como um script de console para detalhes.

org.kde.kirigami_python.desktop

O objetivo principal dos arquivos de entrada de desktop é exibir seu aplicativo no inicializador de aplicativos do Linux. Outro motivo para tê-los é para ter ícones de janela no Wayland, pois eles são necessários para informar ao compositor que "esta janela combina com este ícone".

Ele deve seguir um esquema de nomenclatura DNS reverso seguido pela extensão .desktop, como org.kde.kirigami_python.desktop:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Desktop Entry]
Name=Kirigami Tutorial in Python
Name[ca]=Guia d'aprenentatge del Kirigami en Python
Name[eo]=Lernilo pri Kirigami en Python
Name[es]=Tutorial de Kirigami en Python
Name[fr]=Tutoriel pour Kirigami en Python
Name[it]=Esercitazione di Kirigami in Python
Name[nl]=Kirigami handleiding in Python
Name[pt_BR]=Tutorial do Kirigami em Python
Name[sl]=Učbenik Kirigami v Pythonu
Name[sv]=Kirigami-handledning i Python
Name[tr]=Python ile Kirigami Öğreticisi
Name[uk]=Підручник з Kirigami для Python
Exec=kirigami_hello
Icon=kde
Type=Application
Terminal=false
Categories=Utility

MANIFEST.in

Este arquivo é simplesmente uma declaração de arquivos de código-fonte adicionais que devem estar presentes no pacote quando o aplicativo for executado. Por padrão, o Python não inclui arquivos QML em pacotes, e eles precisam estar disponíveis para que o aplicativo seja executado.

1
include src/qml/*.qml

src/app.py

 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
#!/usr/bin/env python3

import os
import sys
import signal
from importlib.resources import files

from PySide6.QtGui import QGuiApplication
from PySide6.QtCore import QUrl
from PySide6.QtQml import QQmlApplicationEngine

def main():
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()

    """Needed to close the app with Ctrl+C"""
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    """Needed to get proper KDE style outside of Plasma"""
    if not os.environ.get("QT_QUICK_CONTROLS_STYLE"):
        os.environ["QT_QUICK_CONTROLS_STYLE"] = "org.kde.desktop"

    base_path = files('kirigami_python').joinpath('qml', 'Main.qml')
    url = QUrl(f"{base_path}")
    engine.load(url)

    app.exec()

if __name__ == "__main__":
    main()

Como este é um aplicativo GUI, queremos que a função principal seja executada apenas quando o script for executado, não quando for importado. Portanto, precisamos da condição if __name__ == "__main__" no final do arquivo. Consulte [Executando diretamente, como um módulo e como um script de console](/docs/getting-started/python/python-package #running-directly-as-a-module-and-as-a-console-script) para obter detalhes.

Criamos um QGuiApplication e inicializamos o mecanismo QML. Com QGuiApplication.exec(), o aplicativo continuará em execução até ser fechado. Em seguida, importlib.resources.files() obtém o caminho para um arquivo presente no pacote, ou seja, nosso Main.qml. Com esse caminho, carregamos o arquivo QML no mecanismo QML como o ponto de entrada principal para a interface do aplicativo.

src/__init__.py

Crie um arquivo vazio kirigami_python/src/__init__.py. Este arquivo só precisa estar presente para importar um diretório como um pacote.

touch __init__.py

src/__main__.py

Crie um kirigami_python/src/__main__.py com o seguinte conteúdo:

1
2
3
from . import app

app.main()

Isso simplesmente adiciona o conteúdo do diretório atual (src/) e o importa como um módulo chamado app, e então executa imediatamente a função main() do aplicativo.

src/qml/Main.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
// Includes relevant modules used by the QML
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

// Provides basic features needed for all kirigami applications
Kirigami.ApplicationWindow {
    // Unique identifier to reference this object
    id: root

    width: 400
    height: 300

    // Window title
    title: "Hello World"

    // Set the first page that will be loaded when the app opens
    // This can also be set to an id of a Kirigami.Page
    pageStack.initialPage: Kirigami.Page {
        Controls.Label {
            // Center label horizontally and vertically within parent object
            anchors.centerIn: parent
            text: "Hello World!"
        }
    }
}

É aqui que manipularemos o frontend do nosso aplicativo.

Se você conhece um pouco de Javascript, grande parte do QML lhe parecerá familiar (embora tenha suas peculiaridades). A documentação do Qt possui um vasto material sobre esta linguagem, caso você queira experimentar algo por conta própria. Ao longo destes tutoriais, concentraremos grande parte da nossa atenção em nosso código QML, onde podemos usar o Kirigami para aproveitá-lo ao máximo.

Por enquanto, vamos nos concentrar em Main.qml. Primeiro, importamos alguns módulos importantes:

  • QtQuick, a biblioteca padrão usada em aplicativos QML.
  • QtQuick Controls, que fornece uma série de controles padrão que podemos usar para tornar nossos aplicativos interativos.
  • QtQuick Layouts, que fornece ferramentas para posicionar componentes na janela do aplicativo.
  • Kirigami, que fornece uma série de componentes adequados para a criação de aplicativos que funcionam em dispositivos de diferentes formatos e tamanhos.

Chegamos então ao nosso elemento base, Kirigami.ApplicationWindow, que fornece alguns recursos básicos necessários para todos os aplicativos Kirigami. Esta é a janela que conterá cada uma das nossas páginas, as principais seções da nossa interface.

Em seguida, definimos a propriedade id da janela como "root". IDs são úteis porque nos permitem referenciar exclusivamente um componente, mesmo que tenhamos vários do mesmo tipo.

Também definimos a propriedade title da janela como "Hello World".

Em seguida, definimos a primeira página da nossa pilha de páginas. A maioria dos aplicativos Kirigami é organizada como uma pilha de páginas, cada uma contendo componentes relacionados adequados a uma tarefa específica. Por enquanto, estamos mantendo a simplicidade e nos atendo a uma única página. pageStack é uma pilha de páginas inicialmente vazia fornecida por Kirigami.ApplicationWindow, e com pageStack.initialPage:Kirigami.Page {...} definimos a primeira página apresentada ao carregar o aplicativo como uma Kirigami.Page. Esta página conterá todo o nosso conteúdo.

Por fim, incluímos em nossa página um Controls.Label que nos permite inserir texto em nossa página. Usamos anchors.centerIn:parent para centralizar nosso rótulo horizontal e verticalmente dentro do nosso elemento pai. Neste caso, o componente pai do nosso rótulo é Kirigami.Page. A última coisa que precisamos fazer é definir seu texto: text: "Hello World!".

Executando o aplicativo

Você pode executar o script de console kirigami_hello sem precisar instalá-lo primeiro:

pipx run --system-site-packages --spec . kirigami_hello

A flag --system-site-packages é necessária para que o Python tenha acesso aos pacotes Python da sua distribuição. Isso é necessário porque o Kirigami e o PySide precisam ter sido compilados com a mesma versão do Qt para funcionar, o que é o caso quando ambos vêm da distribuição.

A flag --spec determina o caminho para o código-fonte ou pacote wheel que contém o programa, e kirigami_hello é o script executável a ser executado.

Para compilar e instalar o pacote Python, execute:

pipx install --force --system-site-packages .

O pacote será instalado em ~/.local/share/pipx/venvs/kirigami-python, e um script executável será instalado em ~/.local/bin/kirigami_hello.

Depois disso, o aplicativo pode ser iniciado executando:

kirigami_hello

Para executar o novo aplicativo QML no modo para dispositivo móvel, você pode usar QT_QUICK_CONTROLS_MOBILE=1:

QT_QUICK_CONTROLS_MOBILE=1 kirigami_hello

Pronto! Agora você verá seu primeiro aplicativo Kirigami aparecer diante dos seus próprios olhos.

Captura de tela do aplicativo Kirigami gerado