Skip to main content
Перейти до вмісту

Kirigami з Python

Створіть вашу першу програму Kirigami з використанням PySide

Передумови

Перш ніж почати, нам потрібно встановити Kirigami і Python у нашій машині.

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

Якщо ви працюєте у дистрибутиві із застарілими пакунками PySide6 або PyQt6, у цих настановах описано збирання програм за допомогою distrobox.

Структура проєкту

Спочатку ми створимо теку нашого проєкту (ви можете скористатися наведеними нижче командами). Назвемо цю теку kirigami_python/.

kirigami_python/
├── README.md
├── LICENSE.txt
├── MANIFEST.in                        # Щоб додати наші файли QML,
├── pyproject.toml                     # Основний файл для керування проєктом
├── org.kde.kirigami_python.desktop
└── src/
    ├── __init__.py                    # Щоб імпортувати каталог src/ як пакунок,

    ├── __main__.py                    # Щоб вказати програму як точку входу,

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

Назвою пакунка має бути kirigami_python, "виконуваний файл" (скрипт консолі) матиме назву kirigami_hello, а точкою входу буде app.

Складніший проєкт із докладними описами структури файлів наведено на сторінці повного проєкту на Python + Kirigami.

pyproject.toml

Сучасним програмам Python потрібен лише один файл TOML, щоб указати всі метадані, дані щодо пакета і залежності відповідно до PEP 621. Наведений нижче опис є добрим початковим етапом для програми, який може бути розширено пізніше.

Більша частина вмісту цього файла є стандартною, а його повнішу версію можна побачити у підручнику Python з Kirigami: загальна структура.

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

Зверніть увагу на виділені лінії. Як зазначено у розділі Структура проєкту, назвою пакунка є kirigami_python, назвою виконуваного файла — kirigami_hello, а назвою точки входу — app. Зокрема, слід зазначити таке:

  • Скрипт проєкту складається зі скрипту точки входу, який буде створено setuptools для запуску програми, у цьому випадку kirigami_hello.
  • У створеному скрипті проєкту kirigami_hello запускає функцію main() у скрипті app.py пакунка kirigami_python.
  • Типовим каталогом пакетів для проєктів Python зазвичай є кореневий каталог. У цьому випадку його замінено підкаталогом src/, тому цей каталог працює як кореневий каталог пакунка.
  • Інструкція package-dir вказує на те, що створений скрипт проєкту виконує kirigami_python → app, а не kirigami_python → src → app.
  • package-dir є також причиною того, що виклик importlib.resources.files() у app.py виконує kirigami_python → qml → Main.qml, а не kirigami_python → src → qml → Main.qml.

Див. Безпосередній запуск, запуск модуля та запуск скрипту консолі, щоб дізнатися більше.

org.kde.kirigami_python.desktop

Основним призначенням файлів стільничних записів є показ вашої програми у засобі запуску програм у Linux. Іншою причиною їхнього існування є визначення піктограм вікна у Wayland, оскільки вони потрібні для надсилання повідомлення засобу композиції «піктограмою цього вікна є така».

Має виконуватися схема іменування зворотного DNS з наступним суфіксом назви .desktop, наприклад 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

Цей файл є просто оголошенням додаткових файлів початкового коду, які мають бути у пакеті під час запуску програми. Типово, Python не включає файли QML у пакети, а вони мають бути доступними для запуску програми.

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

Оскільки це програма з графічним інтерфейсом користувача, ми хочемо, щоб основна функція запускалася лише під час запуску скрипту, а не під час його імпортування, тому нам потрібна умова if __name__ == "__main__" в кінці файла. Див. Безпосередній запуск, запуск модуля і запуск скрипту консолі, щоб дізнатися більше.

Ми створюємо QGuiApplication та ініціалізуємо механізм QML, і якщо використано QGuiApplication.exec(), програма працюватиме до закриття. Потім importlib.resources.files() захоплює шлях до файла, який є у пакеті, а саме, до нашого Main.qml. За допомогою цього шляху ми завантажуємо файл QML у механізм QML як основну точку входу для інтерфейсу програми.

src/__init__.py

Створіть порожній файл kirigami_python/src/__init__.py. Цей файл просто має бути, щоб можна було імпортувати каталог як пакунок.

touch __init__.py

src/__main__.py

Створіть kirigami_python/src/__main__.py з таким вмістом:

1
2
3
from . import app

app.main()

Це просто додає вміст поточного каталогу (src/) та імпортує його як модуль під назвою app, а потім негайно запускає функцію main() програми.

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

Тут ми працюватимемо із оболонкою нашої програми.

Якщо ви трохи знаєте Javascript, більша частина QML видасться вам знайомою (хоча тут є свої особливості). У документації до Qt є багато матеріалу щодо цієї мови, якщо вам захочеться спробувати щось самостійно. Вивчаючи курс підручника, ми зосередимося на нашому коді QML, де ми використовуватимемо Kirigami, щоб отримати максимальні переваги від цього.

Тепер зосередимо увагу на Main.qml. Спочатку ми імпортуємо декілька важливих модулів:

  • QtQuick, стандартну бібліотеку, яку використовують програми QML.
  • QtQuick Controls, які забезпечують роботу декількох стандартних засобів керування, якими ми можемо скористатися для того, щоб зробити наші програми інтерактивними.
  • QtQuick Layouts, які містять інструменти для розташовування компонентів у вікні програм.
  • Kirigami, яка містить декілька компонентів, які пристосовано для створення програм, що можуть працювати на різних пристроях і екранах з різними формами та розмірами.

Далі, ми перейдемо до нашого базового елемента, Kirigami.ApplicationWindow, який надає певні базові можливості, потрібні для усіх програм Kirigami. Це вікно, які міститиме усі наші сторінки, основні розділи нашого інтерфейсу користувача.

Далі, ми встановимо для властивості id вікна значення 'root'. Ідентифікатори є корисними, оскільки за їх допомогою ми отримуємо унікальну прив'язку до компонента, навіть коли у нас є декілька компонентів одного типу.

Ми також встановлюємо для властивості title значення "Hello World".

Далі, ми визначаємо першу сторінку нашого стосу сторінок. Більшість програм Kirigami упорядковано як стос сторінок — кожну сторінку призначено для виконання окремого завдання. У нашому прикладі ми створимо простий стос, який складатиметься із однієї сторінки. pageStack є початково порожнім стосом сторінок, роботу якого забезпечує Kirigami.ApplicationWindow, і за допомогою pageStack.initialPage: Kirigami.Page{...} ми задаємо для першої сторінки, яку буде показано після завантаження програми, значення Kirigami.Page. Відповідна сторінка міститиме усі наші дані.

Нарешті, ми включаємо до нашої сторінки Controls.Label, яка надасть нам змогу розмістити на нашій сторінці текст. Ми використовуємо anchors.centerIn: parent для центрування нашої мітки горизонтально і вертикально у нашому батьківському елементі. У цьому випадку батьківським для компонента нашої мітки буде компонент Kirigami.Page. Нарешті, ми маємо встановити для мітки текст: text: "Hello World!".

Запуск програми

Ви можете запустити скрипт консолі kirigami_hello без потреби у його попередньому встановленні:

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

Прапорець --system-site-packages потрібен, щоб надати Python доступ до пакунків Python із вашого дистрибутива. Це потрібно, оскільки для роботи Kirigami та PySide мають бути зібрані на основі однієї версії Qt, а це стосується випадків, коли вони обидва походять із дистрибутива.

Прапорець --spec визначає шлях до початкового коду або пакунка wheel, який містить програму, а kirigami_hello є виконуваним скриптом, який слід запустити.

Щоб зібрати і встановити пакунок Python, віддайте такі команди:

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

Пакунок буде встановлено до ~/.local/share/pipx/venvs/kirigami-python, а виконуваний скрипт буде встановлено до ~/.local/bin/kirigami_hello.

Після цього програму можна буде запустити так:

kirigami_hello

Щоб запустити нову програму QML у режимі мобільного пристрою, ви можете скористатися QT_QUICK_CONTROLS_MOBILE=1:

QT_QUICK_CONTROLS_MOBILE=1 kirigami_hello

Ось і все! Тепер ви бачите перед собою вашу першу програму Kirigami вашими власними очима.

Знімок вікна створеної програми Kirigami