Skip to main content
Salti al enhavo

Kirigami kun Python

Kreu vian unuan Kirigami-aplikaĵon per PySide

Antaŭkondiĉoj

Antaŭ ol komenci, ni devos instali Kirigami kaj PySide sur nia maŝino.

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 qqc2-desktop-style AppStream-compose
logo of Linux operating system FedoraFedora
sudo dnf install pipx python3-pyqt6 python3-pyside6 kf6-kirigami-devel flatpak-builder qqc2-desktop-style appstream-compose

If you are on a distribution with old PySide6 or PyQt6 packages, this tutorial works with Building software with distrobox.

Projekta strukturo

Unue ni kreas nian projektan dosierujon (vi povas uzi la komandojn sube). Ni nomos nian kirigami_python/.

kirigami_python/
├── README.md
├── LICENSE.txt
├── MANIFEST.in                        # Por aldoni niajn QML-dosieriojn
├── pyproject.toml                     # La ĉefdosiero por mastrumi la projekton
├── org.kde.kirigami_python.desktop
└── src/
    ├── __init__.py                    # Por enporti la dosierujon src/ kiel pakaĵo

    ├── __main__.py                    # Por signali apon kiel enirpunkton

    ├── app.py
    └── qml/
        └── Main.qml

The package name is going to be kirigami_python, the "executable" (console script) will be called kirigami_hello, and the entrypoint will be app.

For a more comprehensive project that goes into further detail about this file structure, see Full project in Python + Kirigami.

pyproject.toml

Modern Python applications need only a single TOML file to specify all metadata, package information and dependencies as of PEP 621. The following serves as a good starter for an application and can be extended later.

Most of the contents in this file are boilerplate, and a more complete version of it can be seen in Python with Kirigami: General Structure.

 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"]

Note the highlighted lines. As mentioned under Project structure, the name of the package is kirigami_python, the name of the executable is kirigami_hello, and the name of the entrypoint is app. In particular, the following should be noted:

  • The project script consists of an entrypoint script that will be generated by setuptools for the application to run, in this case kirigami_hello.
  • The generated project script kirigami_hello runs the main() function in the app.py script in the kirigami_python package.
  • The default package-dir for Python projects is usually the root directory. In this case, this is overridden with the src/ subdirectory so it acts like it is the root directory of the package.
  • The package-dir is why the generated project script does kirigami_python → app instead of kirigami_python → src → app.
  • The package-dir is also why the importlib.resources.files() call in app.py does kirigami_python → qml → Main.qml instead of kirigami_python → src → qml → Main.qml.

See Running directly, as a module, and as a console script for details.

org.kde.kirigami_python.desktop

La ĉefa celo de Desktop Entry-dosieroj estas montri vian apon sur la aplikaĵlanĉilo en Linukso. Alia kialo por havi ilin estas havi fenestrajn piktogramojn sur Wayland, ĉar ili estas postulataj por diri al la kompostisto "ĉi tiu fenestro konvenas kun ĉi tiu piktogramo".

Ĝi devas sekvi reverse-DNS-nomskemon sekvita de la etendaĵo .desktop kiel ekzemple org.kde.kirigami_python.desktop:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
[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[nl]=Kirigami handleiding in Python
Name[sl]=Učbenik Kirigami v Pythonu
Name[sv]=Kirigami-handledning i Python
Name[uk]=Підручник з Kirigami для Python
Name[x-test]=xxKirigami Tutorial in Pythonxx
Exec=kirigami_hello
Icon=kde
Type=Application
Terminal=false
Categories=Utility

MANIFEST.in

This file is simply a declaration of additional source code files that should be present in the package when the application runs. Python by default doesn't include QML files in packages, and they need to be available in order for the application to run.

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()

Since this is a GUI application, we want the main function to only run when the script is run, not when it's imported, so we need the if __name__ == "__main__" condition at the end of the file. See Running directly, as a module, and as a console script for details.

We create a QGuiApplication and initialize the QML engine, and with QGuiApplication.exec() the application will keep running until closed. Then importlib.resources.files() grabs the path to a file that is present in the package, namely our Main.qml. With that path, we load the QML file into the QML engine as the main entrypoint for the application interface.

src/__init__.py

Create an empty kirigami_python/src/__init__.py file. This file just needs to be present in order to import a directory as a package.

touch __init__.py

src/__main__.py

Kreu dosieron kirigami_python/src/__main__.py kun la jena enhavo:

1
2
3
from . import app

app.main()

This simply adds the contents of the current directory (src/) and imports it as a module named app, then immediately runs the main() function of the application.

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!"
        }
    }
}

Jen kie ni pritraktos la fasadon de nia aplikaĵo.

Se vi konas iom da Javascript, tiam multe de QML ŝajnos al vi konata (kvankam ĝi havas siajn proprajn proprecojn). La dokumentaro de Qt havas ampleksan kvanton da materialo pri ĉi tiu lingvo se vi emas provi ion memstare. Dum ĉi tiuj lerniloj ni koncentriĝos grandan parton de nia atento al nia QML-kodo, kie ni povas uzi Kirigami por akiri la plej grandan parton de ĝi.

Nuntempe, ni koncentriĝu pri Main.qml. Unue ni importas kelkajn gravajn modulojn:

  • QtQuick, la norma biblioteko uzata en QML-aplikoj.
  • QtQuick Controls, kiu provizas kelkajn normajn regilojn, kiujn ni povas uzi por fari niajn aplikaĵojn interagaj.
  • QtQuick Layouts, kiu disponigas ilojn por meti komponentojn ene de la aplika fenestro.
  • Kirigami, kiu provizas kelkajn komponantojn taŭgajn por krei aplikojn, kiuj funkcias trans aparatoj de malsamaj formoj kaj grandecoj.

Ni tiam venas al nia baza elemento, Kirigami.ApplicationWindow, kiu provizas kelkajn bazajn funkciojn necesajn por ĉiuj Kirigami-aplikoj. Ĉi tiu estas la fenestro, kiu enhavos ĉiun el niaj paĝoj, la ĉefaj sekcioj de nia UI.

Ni tiam starigas la id-proprecon de la fenestro al "radiko". ID-oj estas utilaj ĉar ili lasas nin unike referenci komponenton, eĉ se ni havas plurajn de la sama tipo.

We also set the window title property to "Hello World".

Ni tiam starigas la unuan paĝon de nia paĝa stako. Plej multaj Kirigami-aplikoj estas organizitaj kiel stako de paĝoj, ĉiu paĝo enhavante rilatajn komponentojn taŭgajn por specifa tasko. Nuntempe, ni tenas ĝin simpla, kaj algluiĝas al ununura paĝo. pageStack estas komence malplena stako de paĝoj provizita de Kirigami.ApplicationWindow, kaj kun pageStack.initialPage: Kirigami.Page {...} ni agordas la unuan paĝon prezentitan post ŝargo de la aplikaĵo al Kirigami.Paĝo. Ĉi tiu paĝo enhavos nian tutan enhavon.

Fine, ni inkluzivas en nia paĝo Controls.Label kiu ebligas al ni meti tekston sur nia paĝo. Ni uzas anchors.centerIn: parent por centri nian etikedon horizontale kaj vertikale ene de nia gepatra elemento. En ĉi tiu kazo, la gepatra komponanto de nia etikedo estas Kirigami.Paĝo. La lasta afero, kiun ni devas fari, estas agordi ĝian tekston: text: "Saluton Mondo!".

Rulante la aplikaĵon

You can run the kirigami_hello console script without needing to install it first:

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

The flag --system-site-packages is needed to make Python have access to the Python packages from your distribution. This is required because Kirigami and PySide need to have been built against the same Qt version to work, which is the case when both of them come from the distribution.

The flag --spec determines the path to the source code or wheel package that has the program, and kirigami_hello is the executable script to be run.

To build and install the Python package, run:

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

The package will be installed to ~/.local/share/pipx/venvs/kirigami-python, and an executable script will be installed to ~/.local/bin/kirigami_hello.

After this, the application can be launched by running:

kirigami_hello

Por ruli la novan QML-aplikaĵon en movebla reĝimo, vi povas uzi QT_QUICK_CONTROLS_MOBILE=1:

QT_QUICK_CONTROLS_MOBILE=1 kirigami_hello

Jen! Nun vi vidos vian unuan Kirigami-aperon aperi antaŭ viaj propraj okuloj.

Ekrankopio de la generita Kirigami-aplikaĵo