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¶
A script in Krita has two components – the script directory (holding your script’s Python files) and a „.desktop” file that Krita uses to load and register your script. For Krita to load your script both of these must put be in the pykrita subdirectory of your Krita resources folder (See Zarządzanie zasobami for the paths per operating system). To find your resources folder start Krita and click the menu item. This will open a dialog box. Click the Open Resources Folder button. This should open a file manager on your system at your Krita resources folder. See the API docs under „Auto starting scripts”. If there is no pykrita subfolder in the Krita resources directory use your file manager to create one.
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/PythonPlugindla 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=ONw 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/pykritastwórz katalog o nazwie
mojawtyczkaplik o nazwie
mojawtyczka.desktop
- w swoim katalogu Krita
- w katalogu
mojawtyczkautwórz plik o nazwie
__init__.pyplik o nazwie
mojawtyczka.py
- w katalogu
w pliku
__init__.pyumieść 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¶
Extensions are relatively simple python scripts that run on Krita start. They are made by extending the Extension class, and the most barebones extension looks like this:
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.
First, let’s create an action. We can do that easily with Window.createAction(). Krita will call createActions for every Window that is created and pass the right window object that we have to use.
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¶
Creating a custom docker is much like creating an extension. Dockers are in some ways a little easier, but they also require more use of widgets. This is the barebones docker code:
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.