Jak stworzyć wtyczkę Pythona dla Krity¶
Możesz posiadać swoje ciekawie napisane skrypty w środowisku uruchomieniowym Scripter Python, które możesz chcieć uruchamiać samoczynnie dla wystąpienie. Owijając swój skrypt we wtyczkę, możesz nadać mu więcej możliwości, niż te które ma, będąc wykonywanym z edytora Scripter.
Ok, więc nawet jeśli znasz bardzo dobrze Pythona, to istnieje kilka szczegółów odnośnie tego jak Krita rozpoznaje wtyczki Pythona. Ta strona daje pogląd na temat tego jak tworzyć różne rodzaje skryptów Pythona, które są wyjątkowe dla Krity.
Te mini-samouczki zostały napisane dla ludzi o podstawowej wiedzy nt Pythona i przez to mają zachęcać ludzi do próbowania zamiast zwykłego powielana kodu, więc czytaj ten tekst uważnie.
Umożliwienie Kricie rozpoznanie twojej wtyczki¶
Skrypt w Kricie ma dwa składniki – katalog skryptu (zawierający twoje pliki skryptów Python) oraz plik „.desktop”, których Krita używa do wczytywania i rejestrowania twoich skryptów. Aby Krita mogła wczytać twój skrypt, to oba te składniki muszą znaleźć się w podkatalogu pykrita
twojego katalogu zasobów Krity (Aby poznać ścieżki dla danego systemu operacyjnego zajrzyj do ref:resource_management). Aby odnaleźć swój katalog zasobów, uruchom Kritę i wybierz z menu . Otworzy to okno dialogowe. Naciśnij na przycisk Otwórz katalog zasobów. Powinno to otworzyć przeglądarkę plików na twoim systemie w miejscu zasobów Krity. Zajrzyj do dokumentacji API w miejscu „Samoczynne uruchamianie skryptów”. Jeśli nie ma podkatalogu pykrita
w katalogu zasobów Krity, to użyj swojej przeglądarki plików, aby taki stworzyć.
Skrypty są rozpoznawane po plikach, które są zakończone rozszerzeniem .``.desktop``, który zawiera dane o samym skrypcie.
Dlatego, dla każdej wtyczki będziesz musiał stworzyć katalog i dodać plik desktop.
Plik desktop powinien wyglądać następująco:
[Desktop Entry]
Type=Service
ServiceTypes=Krita/PythonPlugin
X-KDE-Library=mojawtyczka
X-Python-2-Compatible=false
X-Krita-Manual=podręcznikMojejWtyczki.html
Name=Moja własna wtyczka
Comment=Nasza własna wtyczka.
- Rodzaj
To zawsze powinno usługą.
- ServiceTypes
To zawsze powinno być
Krita/PythonPlugin
dla wtyczek Pythona.- X-KDE-Library
To powinno być nazwą katalogu wtyczki, którą właśnie stworzyłeś.
- Zgodne-z-X-Python-2
Określa czy jest zgodne z Pythonem 2. Jeśli Krita została zbudowana na Pythonie 2 zamiast 3 (
-DENABLE_PYTHON_2=ON
w ustawieniach cmake), to wtyczka ta nie pojawi się na liście.- X-Krita-Manual
Opcjonalna wartość, która będzie wskazywać na element menu. Jest to pokazywane w zarządzaniu wtyczkami Pythona. Jeśli jest to plik HTML, to zostanie pokazany jako tekst formatowany <https://doc.qt.io/qt-5/richtext-html-subset.html>`_, a jeśli nie, to jako zwykły tekst.
- Nazwa
Nazwa, która pojawi się w zarządzaniu wtyczkami Pythona.
- Komentarz
Opis, który pojawi się w zarządzaniu wtyczkami Pythona.
Wtyczki Pythona dla Krity muszą być modułami Python, więc upewnij się, że zawierają one skrypt __init__.py
, który zawiera coś takiego…
z .mojawtyczka import *
Gdzie .myplugin jest nazwą głównego pliku twojej wtyczki. Jeśli uruchomisz Kritę ponownie, to powinno się to pojawić w Zarządzaniu Wtyczkami Pythona w ustawieniach, lecz będzie wyszarzone, bo nie ma myplugin.py. Jeśli najedziesz na wyłączone wtyczki, to zobaczysz na nich błąd.
Informacja
Musisz jednoznacznie włączyć swoją wtyczkę. Przejdź do menu ustawień, otwórz okno dialogowe Ustawienia Krity i przejdź do strony zarządzania wtyczkami Pythona, gdzie musisz włączyć swoją wtyczkę.
Podsumowanie¶
Podsumowując, jeśli chcesz stworzyć skrypt o nazwie mojawtyczka
:
- w swoim katalogu Krita
resources/pykrita
stwórz katalog o nazwie
mojawtyczka
plik o nazwie
mojawtyczka.desktop
- w swoim katalogu Krita
- w katalogu
mojawtyczka
utwórz plik o nazwie
__init__.py
plik o nazwie
mojawtyczka.py
- w katalogu
w pliku
__init__.py
umieść ten kod:
z .mojawtyczka import *
w pliku desktop umieść ten kod:
[Desktop Entry] Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=mojawtyczka X-Python-2-Compatible=false Name=Moja własna wtyczka Comment=Nasza własna wtyczka.
napisz swój skrypt w pliku
'mojawtyczka/mojawtyczka.py'
.
Tworzenie rozszerzenia¶
Rozszrzenia są stosunkowo prostymi skryptami Pythona, które są uruchamiane wraz z uruchomieniem Krity. Są stworzone jako rozszerzenia klas, a najbardziej podstawowe rozszerzenie wygląda tak:
from krita import *
class MyExtension(Extension):
def __init__(self, parent):
#To rozpoczyna element nadrzędny, zawsze ważne przy tworzeniu klas pochodnych.
super().__init__(parent)
def setup(self):
pass
def createActions(self, window):
pass
# Oraz dodaj rozszerzenie do listy rozszerzeń Krity:
Krita.instance().addExtension(MyExtension(Krita.instance()))
Ten kod oczywiście nie robi nic. w createActions zazwyczaj dodajemy działania Krity, tak abyśmy mogli uzyskać dostęp do naszego skryptu z menu Narzędzia.
Najpierw utwórzmy działanie. Możemy to łatwo zrobić poprzez Window.createAction(). Krita wywoła createActions dla każdego Okna, które zostanie stworzone i przekaże właściwy obiekt okna, którego musimy użyć.
Więc…
def createActions(self, window):
action = window.createAction("mojeDziałanie", "Mój skrypt", "tools/scripts")
- „mojeDziałanie”
To powinno być zastąpione niepowtarzalnym ID, którego Krita użyje do znalezienia działania.
- „Mój skrypt”
To co jest widoczne w Menu narzędzi.
Teraz jeśli ponownie uruchomisz Kritę, to będziesz miał działanie o nazwie „Mój skrypt”. Nadal nie robi on nic, bo nie podłączyliśmy go do skryptu.
Tak więc, przygotujmy prosty skrypt do eksportu dokumentów. Dodaj następujące wiersze do rozszerzonej klasy, upewnij się, że jest powyżej względem tego, gdzie dodajesz rozszerzenie do Krity:
def exportDocument(self):
# Pobierz dokument:
doc = Krita.instance().activeDocument()
# Zapisanie nieistniejącego dokumentu powoduje usterkę, więc sprawdź to najpierw.
if doc is not None:
# To wywołuje okno dialogowe zapisu. Okno to zwraca daną rodzaju tuple.
fileName = QFileDialog.getSaveFileName()[0]
# Oraz wyeksportuj dokument do miejsca określonego zmienną fileName.
# InfoObject jest słownikiem z danymi ustawieniami eksportu, lecz gdy będzie pusty, to Krita użyje domyślnych ustawień.
doc.exportImage(fileName, InfoObject())
Oraz dodaj import dla QFileDialog powyżej przy użyciu następujących wierszy:
from krita import *
from PyQt5.QtWidgets import QFileDialog
Następnie, aby podłączyć działanie do nowo wyeksportowanego dokumentu:
def createActions(self, window):
action = window.createAction("mojeDziałanie", "Mój skrypt")
action.triggered.connect(self.exportDocument)
Jest to przykład połączenia sygnał/slot, którego aplikacje Qt, takie jak Krita, często używają. Przejdziemy przez to jak tworzyć własne sygnały i sloty trochę później.
Uruchom Kritę ponownie, a twoje nowe działanie powinno teraz móc eksportować dokumenty.
Tworzenie skrótów klawiszowych do ustawienia¶
Teraz, twoje nowe działanie nie pokazuje się w
.Krita, z różnych powodów, dodaje działania tylko do Ustawienia skrótów, gdy są dostępne w pliku .action. Plik .action
powinien wyglądać następująco, aby można było z niego dodać skróty:
<?xml version="1.0" encoding="UTF-8"?>
<ActionCollection version="2" name="Scripts">
<Actions category="Scripts">
<text>Moje skrypty</text>
<Action name="myAction">
<icon></icon>
<text>Mój skrypt</text>
<whatsThis></whatsThis>
<toolTip></toolTip>
<iconText></iconText>
<activationFlags>10000</activationFlags>
<activationConditions>0</activationConditions>
<shortcut>ctrl+alt+shift+p</shortcut>
<isCheckable>false</isCheckable>
<statusTip></statusTip>
</Action>
</Actions>
</ActionCollection>
- <text>Moje skrypty</text>
Stworzy to podkategorię w skryptach o nazwie „Moje skrypt”, aby dodać do nich skróty.
- nazwa
To powinno być niepowtarzalnym ID, który nadałeś swojemu działaniu przy tworzeniu go w ustawieniach rozszerzenia.
- ikona
Nazwa możliwej ikony. Pokaże się to tylko w Plazmie KDE, bo użytkownicy Gnome oraz Windowsa narzekali, że wygląda to brzydko.
- tekst
Tekst, który pojawi się w edytorze skrótów.
- coTo
Tekst, który wyświetli się po wywołaniu «co to jest», co jest działaniem skierowanym na pomoc użytkownikowi.
- Podpowiedź
Wskazówka narzędzia, która pojawi się po najechaniu na nie.
- tekstIkony
Tekst pojawi się teraz, gdy będzie wyświetlany na pasku narzędzi. Na przykład „Zmień rozmiar obrazu do nowego” można skrócić do „Zmień rozmiar obrazu”, aby zaoszczędzić przestrzeń, tak więc umieścilibyśmy to tutaj.
- flagiUruchomienia
Określa to kiedy działanie jest wyłączone, a kiedy nie.
- warunkiUruchomienia
Określa to warunki uruchomienia (np. uruchom tylko gdy zaznaczenie jest możliwe do zmiany). Po przykłady obejrzyj kod.
- skrót
Domyślny skrót.
- isCheckable
Określa czy to jest pole zaznaczane, czy nie.
- wskazówkaStanu
Wskazówka stanu wyświetlana na pasku stanu.
Zapisz ten plik jako myplugin.action
, gdzie myplugin jest nazwą twojej wtyczki. Plik działania powinien zostać zapisany, nie w katalogu zasobów pykrita, lecz raczej w katalogu zasobów o nazwie „actions”. (Tak więc, share/pykrita
jest miejscem, do którego trafiają wtyczki pythona i pliki desktop, a share/actions
gdzie trafiają pliki działań) Uruchom Kritę ponownie. Skrót powinien teraz pojawić się na liście skrótów.
Tworzenie doku¶
Tworzenie własnego doku jest podobne do tworzenia rozszerzenia. Doki są w pewnym sensie łatwiejsze, lecz wymagają także większego używania elementów interfejsu. Jest to szkielet kod doku:
from PyQt5.QtWidgets import *
from krita import *
class MyDocker(DockWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("My Docker")
def canvasChanged(self, canvas):
pass
Krita.instance().addDockWidgetFactory(DockWidgetFactory("myDocker", DockWidgetFactoryBase.DockRight, MyDocker))
Tytuł okna pojawi się na liście doku w Kricie. canvasChanged musi być zawsze obecny, lecz nie musisz z nim nic robić, więc wystarczy, że dodasz «pass».
Dla addDockWidgetFactory…
- „mójDok”
Zastąp to niepowtarzalnym ID dla twojego doku, którego Krita używa, aby to działanie śledzić.
- DockWidgetFactoryBase.DockRight
Położenia. Może to być
DockTornOff
,DockTop
,DockBottom
,DockRight
,DockLeft``lub ``DockMinimized
- MójDok
Zastąp to nazwą klasy doku, który chcesz dodać.
Tak więc, jeśli dodamy naszą funkcję eksportu dokumentu, którą utworzyliśmy w tym dziale rozszerzenia do kodu doku, to jak mamy umożliwić użytkownikowi jego używanie? Najpierw, potrzebujemy trochę kodu interfejsu Qt: Dodajmy przycisk!
Domyślnie Kirta używa PyQt, lecz jego dokumentacja jest bardzo słaba, zazwyczaj ponieważ dokumentacja Qt jest na prawdę dobra i często zauważysz, że dokumentacja PyQt klasy, mówi , QWidget tak jakby była to dziwna kopia zwykłej dokumentacji Qt dla tej klasy.
Mimo wszystko, to co musimy najpierw zrobić, to utworzyć QWidget
, co nie jest trudne. Wystarczy dodać pod setWindowTitle
:
mainWidget = QWidget(self)
self.setWidget(mainWidget)
Następnie tworzymy przycisk:
buttonExportDocument = QPushButton("Eksportuj dokument", mainWidget)
Teraz, aby podłączyć nasz przycisk do funkcji, będziemy musieli spojrzeć na sygnały w dokumentacji. QPushButton ma swoje niepowtarzalne sygnały, lecz mówi także, że dziedziczy 4 sygnały z QAbstractButton, co oznacza, że możemy ich także użyć. W tym przypadku, chcemy sygnału „clicked”.
buttonExportDocument.clicked.connect(self.exportDocument)
Teraz jeśli ponownie uruchomimy Kritę, to będziemy mieli nowy dok, a w nim przycisk. Naciśnięcie na nim wywoła funkcję eksportu.
Jednakże, przycisk jest trochę dziwnie wyrównany. Powodem jest to, że nasz mainWidget
nie ma układu. Nadajmy mu szybko taki układ:
mainWidget.setLayout(QVBoxLayout())
mainWidget.layout().addWidget(buttonExportDocument)
Qt ma kilka układów, lecz QHBoxLayout oraz QVBoxLayout są najłatwiejszymi w użyciu, bo układają elementy interfejsu w poziomie i pionie.
Uruchom Kritę ponownie, a przycisk powinien być teraz ładnie rozmieszczony.
Sygnały i sloty PyQt¶
Już używaliśmy sygnałów i slotów PyQt, lecz czasami potrzebujesz utworzyć swój własny sygnał i slot. Jako iż dokumentacja PyQt jest całkiem trudna w zrozumieniu, oraz z tego powodu, że tworzenie sygnałów i slotów różni się bardzo od tego w C++ Qt, to wyjaśniliśmy to tutaj:
Wszystkie funkcje, które tworzysz w PyQt, są także rozumiane jako sloty, co oznacza, że można je podłączyć do sygnałów takich jak Action.triggered` lub ``QPushButton.clicked
. Jednakże QCheckBox
ma sygnał dla toggled, który wysyła zmienną zerojedynkową. Jak sprawić, aby nasza funkcja przyjmowała zmienną zerojedynkową?
Najpierw upewnij się, czy masz właściwe wiersze importujące do tworzenia własnych slotów:
from PyQt5.QtCore import pyqtSlot
(Jeśli istnieje from PyQt5.QtCore import *
na liście importów, to oczywiście nie musisz tego robić.)
Następnie, musisz dodać definicję slotu PyQt przed swoją funkcją:
@pyqtSlot(bool)
def myFunction(self, enabled):
enabledString = "disabled"
if (enabled == True):
enabledString = "enabled"
print("Pole zaznaczane jest "+enabledString)
Gdy już utworzysz swoje pole zaznaczane, to możesz zrobić coś takiego myCheckbox.toggled.connect(self.myFunction).
Podobnie, aby tworzyć swoje własne sygnały PyQt, robisz następującą rzecz:
# nazwa sygnału jest dodana do zmiennych członkowskich klasy
signal_name = pyqtSignal(bool, name='signalName')
def emitMySignal(self):
# A oto sposób w jaki wywołujesz wysyłanie sygnału.
self.signal_name.emit(True)
I użyj właściwych wierszy importu:
from PyQt5.QtCore import pyqtSignal
Aby wywołać lub stworzyć sloty dla obiektów, które nie są standardowymi obiektami Pythona, musisz tylko zawrzeć ich nazwy w cudzysłowach.
Uwaga dotycząca testów jednostkowych¶
Jeśli chcesz napisać testy jednostkowe dla twojej wtyczki, to spójrz na makieta modułu Krity.
Wnioski¶
Ok, więc to pokrywa wszystkie szczegóły dotyczące tworzenia wtyczek Pythona. Nie zajmuje się jednak tym jak przetwarzać dane pikselowe, czy najlepszych praktyk związanych z dokumentami, lecz jeśli masz już trochę doświadczenia z Pythonem, to powinieneś móc rozpocząć tworzyć swoje własne wtyczki.
Jak zawsze, przeczytaj kod uważnie, a także dokumentację API dla Pythona, Krity oraz Qt, aby zobaczyć, co jest możliwe, a tym sposobem zajdziesz daleko.