Krita’da Python eklentisi yapımı¶
Betikleyici Python penceresinde gayet güzel betikler yazmış olabilirsiniz; ancak belki daha fazlasını yapmak isterseniz; örneğin kendiliğinden çalıştırmak gibi, onları bir eklenti içine koyarak Betikleyici düzenleyicisinden çok daha fazla güç ve esneklik kazanabilirsiniz.
Tamam, Python’u gerçekten iyi biliyor olsanız bile, Krita’nın bir Python eklentisini tanımasını sağlamak için bazı küçük ayrıntılar vardır. Bu yüzden bu sayfa, Krita’ya özgü çeşitli Python betik türlerinin nasıl oluşturulacağına dair genel bir bakış sunacaktır.
Bu mini öğreticiler, temel python bilgisine sahip kişiler için ve kodu kopyalayıp yapıştırmak yerine denemeyi teşvik edecek şekilde yazılmıştır, bu nedenle metni dikkatlice okuyun.
Krita’nın eklentinizi tanımasını sağlamak¶
Krita’daki bir betiğin iki bileşeni vardır – betik dizini (betiğinizin Python dosyalarını içeren dosyalar) ve Krita’nın betiğinizi kaydetmek ve yüklemek için kullandığı bir “.desktop” dosyası. Krita’nın betiğinizi yükleyebilmesi içim bu iki dosya, Krita özkaynaklarınızın pykrita
alt dizinine koyulmalıdır (işletim sistemlerinin kullandığı yollar için Özkaynak Yönetimi bölümüne bakın. Özkaynaklar klasörünüzü bulmak için Krita’yı başlatın ve menü ögesine tıklayın. Bu, bir iletişim kutusu açar. Özkaynaklar Klasörünü Aç düğmesine tıklayın. Bu bir dosya yöneticisinde Krita’nın özkaynaklar klasörünü gösterir. “Auto starting scripts” hakkındaki API belgelerine bakın. Krita özkaynaklar dizininde bir pykrita
klasörü yoksa bir tane yaratmak için dosya yöneticinizi kullanın.
Betikler, betiğin kendisi üzerine bilgi veren bir .desktop
dosyasıyla tanımlanırlar.
Bundan dolayı, her bir doğru betik için bir klasör ve bir Desktop dosyası yaratmanız gerekir.
Desktop dosyası aşağıdaki gibi görünmelidir:
[Desktop Entry]
Type=Service
ServiceTypes=Krita/PythonPlugin
X-KDE-Library=eklentim
X-Python-2-Compatible=false
X-Krita-Manual=myPluginManual.html
Name=Benim Eklentim
Comment=Benim yaptığım eklentim.
- Type
Bu, her zaman bir hizmet olmalıdır.
- ServiceTypes
Python eklentileri için bu her zaman
Krita/PythonPlugin
olmalıdır.- X-KDE-Library
Bu, şimdi yarattığınız eklenti klasörünün adı olmalıdır.
- X-Python-2-Compatible
Python 2 ile uyumlu olup olmadığı. Krita Python 3 yerine 2 ile yapılmışsa (cmake yapılandırmasında
-DENABLE_PYTHON_2=ON
) bu eklenti listede görünmez.- X-Krita-Manual
Elle belirtilen ögeye işaret eden isteğe bağlı bir değer. Bu, Python Eklentisi Yöneticisi’nde gösterilir. Bir HTML dosyasıysa zengin metin olarak gösterilir, değilse düz metin olarak kullanılır.
- Ad
Python Eklentisi Yöneticisi’nde gösterilecek ad.
- Comment
Python Eklentisi Yöneticisi’nde gösterilecek açıklama.
Krita’nın Python eklentilerinin Python modülleri olması gerekir, bu nedenle şöyle bir şeyler içeren bir __init__.py
betiğinin olduğundan emin olun…
from .eklentim import *
.eklentim, eklentinizin ana dosyasının adıdır. Krita’yı yeniden başlatırsanız Ayarlar’da Python Eklentisi Yöneticisi bölümünde bu adla görünmelidir. Henüz gridir; çünkü bir eklentim.py dosyası yoktur. Devre dışı bırakılan eklentilerin üzerine fareyle gelirseniz hatanın kendisini görebilirsiniz.
Not
Eklentinizi açıkça etkinleştirmeniz gerekir. Ayarlar menüsünden Krita’yı Yapılandır iletişim kutusunu açıp Python Eklentisi Yöneticisi sekmesine gidin ve eklentinizi etkinleştirin.
Özet¶
Özet olarak, eklentim
adında bir betik oluşturmak istiyorsanız:
resources/pykrita
Krita dizininde şunları oluşturun:eklentim
adında bir klasöreklentim.desktop
adında bir dosya
eklentim
klasöründe şunları oluşturun:__init__.py
adında bir dosyaeklentim.py
adında bir dosya
__init__.py
dosyasına şu kodu koyun:
from .eklentim import *
desktop dosyasına şu kodu koyun:
[Desktop Entry] Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=eklentim X-Python-2-Compatible=false Name=Kendi Eklentim Comment=Kendi yazdığım eklenti.
betiğinizi
eklentim/eklentim.py
dosyasında yazın.
Bir uzantı oluşturmak¶
Uzantılar, Krita’nın başlangıcında çalışan görece yalın Python betikleridir. Extension sınıfını genişleterek yapılırlar ve en temel uzantılar şöyle görünürler:
from krita import *
class Uzantım(Extension):
def __init__(self, parent):
# Bu, üst ögeyi ilklendirir, alt sınıflara ayırırken önemlidir.
super().__init__(parent)
def setup(self):
pass
def createActions(self, window):
pass
# Uzantıyı, Krita'nın uzantılar listesine ekleyin:
Krita.instance().addExtension(Uzantım(Krita.instance()))
Bu kod doğal olarak bir şey yapmaz. Tipik olarak, createActions içinde Krita’ya eylemler ekler ve Araçlar menüsünden betiğimize erişiriz.
İlk olarak, bir eylem oluşturalım. Bunu, Window.createAction() ile kolaylıkla yapabiliriz. Krita, oluşturulan her bir pencere için createActions’ı çağırır ve kullanmak durumunda olduğumuz doğru pencere nesnesini geçirir.
Demeli…
def createActions(self, window):
action = window.createAction("eylemim", "Betiğim", "tools/scripts")
- “eylemim”
Bu, Krita’nın eylemi bulmak için kullanacağı benzersiz bir kimlikle değiştirilmelidir.
- “Betiğim”
Bu, Araçlar Menüsü içinde görünür olacak şeydir.
Krita’yı şimdi yeniden başlatırsanız “Betiğim” adında bir eyleminiz olacaktır. Henüz bir şey yapmaz; çünkü onu bir betiğe bağlamadık.
Şimdi basit bir belge dışa aktarma betiği yapalım. Aşağıdakini Extension sınıfına ekleyin; onun Krita’ya uzantıları eklediğiniz yerin üzerinde olduğundan emin olun.
def exportDocument(self):
# Belgeyi alın:
doc = Krita.instance().activeDocument()
# Var olmayan bir belgeyi kaydetmek çökmeye neden olur, buna bakalım.
if doc is not None:
# Bu, bir ikili döndüren kaydet iletişim kutusunu çağırır.
fileName = QFileDialog.getSaveFileName()[0]
# Belgeyi fileName konumuna dışa aktarın.
# InfoObject, belirli dışa aktarma seçenekleri içeren bir sözlüktür; ancak boş bir tane yaparsak Krita öntanımlı dışa aktarma ayarlarını kullanır.
doc.exportImage(fileName, InfoObject())
İçe aktarmayı yukarıda QFileDialog ile ekleyin:
from krita import *
from PyQt5.QtWidgets import QFileDialog
Sonrasında, eylemi yeni dışa aktarılan belgeye bağlayın:
def createActions(self, window):
action = window.createAction("eylemim", "Betiğim")
action.triggered.connect(self.exportDocument)
Bu, Krita gibi Qt uygulamalarının çok kullandığı bir sinyal/yuva bağlantısı örneğidir. Kendi sinyallerimizi ve yuvalarımızı yapmayı daha sonra göreceğiz.
Krita’yı yeniden başlatın ve yeni eyleminiz artık belgeyi dışa aktarmalıdır.
Yapılandırılabilir klavye kısayolları oluşturmak¶
Şimdi, yeni eyleminiz
bölümünde görünmez.Krita, çeşitli nedenlerden dolayı eylemleri yalnızca bir .action
dosyasında varken Kısayol Ayarları bölümüne ekler. Eylemimizi kısayollara eklemek için gereken eylem dosyası şuna benzemelidir:
<?xml version="1.0" encoding="UTF-8"?>
<ActionCollection version="2" name="Scripts">
<Actions category="Scripts">
<text>My Scripts</text>
<Action name="myAction">
<icon></icon>
<text>My Script</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>Betiklerim</text>
Bu, kısayollarınızı eklemeniz için “Betiklerim” adında bir alt kategori oluşturur
- name
Bu, uzantının kurulumunda eyleminizi oluştururken oluşturduğunuz benzersiz kimlik olmalıdır.
- icon
Olası bir simgenin adı. GNOME ve Windows kullanıcıları çirkin göründüklerinden şikayet ettikleri için bunlar yalnızca KDE Plasma’da görünecek.
- text
Kısayol düzenleyicide görünecek metin.
- whatsThis
Bir Qt uygulaması, bir yardım eylemi olan ‘Bu Nedir?’i çağırdığında görünecek metin.
- toolTip
Fareyle üzerine gelindiğinde görünecek olan araç ipucu.
- iconText
Bir araç çubuğunda gösterilecek metin. Örneğin, “Görseli Yeni Bir Boyuta Yeniden Boyutlandır” adlı bir kısayol “Görseli Boyutlandır” olarak kısaltılabilir.
- activationFlags
Bu, bir eylemin ne zaman devre dışı olup olmadığını belirler.
- activationConditions
Bu, etkinleştirme koşullarını belirler (örneğin, yalnızca seçim düzenlenebilirken etkinleştir). Örnekler için koda bakın.
- shortcut
Öntanımlı kısayol.
- isCheckable
Bunun bir onay kutusu olup olmadığı.
- statusTip
Bir durum çubuğunda görüntülenen durum ipucu.
Bu dosyayı, eklentim.action
olarak kaydedin; burada eklentim, eklentinizin adıdır. Eylem dosyası pykrita özkaynaklar klasöründe değil de “actions” adındaki bir klasörde kaydedilmelidir (Demeli, share/pykrita
Python eklentilerinin ve Desktop dosyalarının koyulduğu klasörken share/actions
ise eylem dosyalarının klasörüdür). Krita’yı yeniden başlatın. Kısayol artık kısayol eylem listenizde görünmelidir.
Bir panel oluşturmak¶
Özel bir panel oluşturmak, aynı bir uzantı oluşturmak gibidir. Paneller biraz daha kolaydır; ancak daha fazla araç takımı kullanımı gerektirirler. Temel panel kodu şöyledir:
from PyQt5.QtWidgets import *
from krita import *
class MyDocker(DockWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Panelim")
def canvasChanged(self, canvas):
pass
Krita.instance().addDockWidgetFactory(DockWidgetFactory("panelim", DockWidgetFactoryBase.DockRight, MyDocker))
Pencere başlığı, Krita’nın paneller listesinde nasıl görüneceğini belirler. canvasChanged’in her zaman olması gerekir; ancak onunla bir şey yapmanız gerekmeyebilir; dolayısıyla ‘pass’ yapabilirsiniz.
addDockWidgetFactory için…
- “panelim”
Bunu, Krita’nın panelinizi takip etmek için kullanacağı benzersiz bir kimlikle değiştirin.
- DockWidgetFactoryBase.DockRight
Konumu. Bunlar;
DockTornOff
,DockTop
,DockBottom
,DockRight
,DockLeft
veyaDockMinimized
olabilir.- MyDocker
Bunu, eklemek istediğiniz panelin sınıfının adıyla değiştirin.
Böyleyken, uzantı bölümündeki belge dışa aktarma işlevimizin kodunu bu panel koduna eklemek istersek, kullanıcının onu nasıl etkinleştirmesini sağlayabiliriz? Biraz Qt Grafik Arabirim kodlaması yapmamız gerekecek: Haydi bir düğme ekleyelim!
Öntanımlı olarak Krita PyQt kullanır; ancak belgelendirmesi pek kötüdür; aslında bunun nedeni özünde Qt belgelendirmesinin çok iyi olduğundan bunu kötüymüş gibi göstermesidir. Örneğin, QWidget sınıfının PyQt belgelendirmesi, o sınıf için olan olağan Qt “belgelendirmesinin garip bir kopyası gibidir.
Her neyse, ilk yapmamız gereken bir QWidget
eklemek; setWindowTitle
altında şunu ekleyin:
mainWidget = QWidget(self)
self.setWidget(mainWidget)
Sonrasında bir düğme ekliyoruz:
buttonExportDocument = QPushButton("Belgeyi Dışa Aktar", mainWidget)
Şimdi, düğmemizi işlevimize bağlamak için belgelendirmedeki sinyallere bakacağız. QPushButton ögesinin kendine özel benzersiz sinyalleri yoktur; ancak QAbstractButton ögesinden 4 sinyal devraldığını yazar. Bu da onları da kullanabileceğimiz anlamına gelir. Bizim istediğimiz ‘clicked’.
buttonExportDocument.clicked.connect(self.exportDocument)
Krita’yı şimdi yeniden başlatırsak yeni bir panelimiz ve o panelde yeni bir düğmemiz olacak. Düğmeye tıklamak, dışa aktarma işlevini çağırır.
Hmm, düğme düzgünce hizalanmamış gibi duruyor. Bunun nedeni, mainWidget
ögemizin herhangi bir yerleşime sahip olmaması. Tez yapalım:
mainWidget.setLayout(QVBoxLayout())
mainWidget.layout().addWidget(buttonExportDocument)
Qt’nin birkaç yerleşimi vardır; ancak QHBoxLayout ve QVBoxLayout <https://doc.qt.io/qt-5/qboxlayout.html>, kullanımı en kolay olanlardır; bunlar araç takımlarını yatay veya dikey olarak düzenlerler.
Krita’yı yeniden başlatın ve düğmenin güzelce yerleştirilmiş olduğunu göreceksiniz.
PyQt Sinyalleri ve Yuvaları¶
PyQt sinyallerini ve yuvalarını halihazırda kullandık; ancak PyQt’nin belgelendirmesini anlamak pek güç olduğundan ve sinyal ve yuva oluşturmanın Qt C++’den pek farklı olduğundan kendi sinyallerinizi ve yuvalarınızı oluşturmak isteyeceksiniz. Bunu, burada anlattık:
PyQt’de yaptığınız tüm Python işlevlerine yuva denebilir; yani, bunlar Action.triggered
veya QPushButton.clicked
gibi sinyallere bağlanabilirler. Ancak, QCheckBox
ögesinin açma/kapatma işlevi için bir Boole değeri sinyali vardır. İşlevimizin bu Boole değerini anlamasını nasıl sağlarız?
Öncelikle, özel yuvalar yapmak için doğru kitaplığı içe aktardığımızdan emin olalım:
from PyQt5.QtCore import pyqtSlot
(İçe aktarmalar içinde halihazırda bir from PyQt5.QtCore import *
varsa bunu yapmanıza gerek yoktur.)
Sonrasında, işlevinizden önce bir PyQt yuva tanımı eklemeniz gerekir:
@pyqtSlot(bool)
def myFunction(self, enabled):
enabledString = "devre dışı"
if (enabled == True):
enabledString = "etkin"
print("Onay kutusu "+enabledString)
Onay kutunuzu etkinleştirdikten sonra myCheckbox.toggled.connect(self.myFunction) gibi bir şey yapabilirsiniz.
Benzer olarak, kendi PyQt sinyalleriniz için şunu yaparsınız:
# sinyal adı, sınıfın üye değişkenlerine eklenir
signal_name = pyqtSignal(bool, name='signalName')
def emitMySignal(self):
# Bu da yayılacak sinyalin nasıl tetikleneceğidir.
self.signal_name.emit(True)
Doğru içe aktarmayı kullanmayı unutmayın:
from PyQt5.QtCore import pyqtSignal
Standart Python nesnesi olmayan nesneler için yuvalar yaymak veya oluşturmak için onların adlarını tırnak içine almanız yeterlidir.
Birim sınamaları üzerine bir not¶
Eklentiniz için birim sınamaları yazmak istiyorsanız mock Krita modülüne bakın.
Sonuç¶
Bu belge, Python eklentileri oluşturmak için Krita’ya özgü tüm ayrıntıları kapsıyor. Piksel verisinin nasıl ayrıştırılacağını veya belgelerle ilgili en iyi uygulamaları ele almaz; ancak Python ile biraz deneyiminiz varsa kendi eklentilerinizi oluşturmaya başlayabilmeniz gerekir.
Her zaman dediğimiz gibi; Krita, Python ve Qt API belgelerini okuyun. Kısa zamanda çok mesafe katedersiniz.