「Krita」と「Python」のクラスでダイアログを使ってみよう
はじめに
今回は第8回で解説した、ダイアログ(QDialog)に付けるUIパーツなどをクラスを継承してプログラミングします。QDialogクラスを継承した「Dialog」クラスを宣言することで、Dialogクラス内でQDialogクラスのメソッドやプロパティが「self.」を付けて使えます。
今回用意したのは「素のダイアログ(QDialog)」「ラベル(QLabel)」「プッシュボタン(QPushButton)」「スライダー(QSlider)」「ラインエディット(QLineEdit)」「フォントコンボボックス(QFontComboBox)」を使ったサンプルです。「フォントコンボボックス(QFontComboBox)」だけ新たに解説しますが、これまでと同様に操作すれば簡単に実装できます。
素のダイアログを継承したクラスを使う
今回のサンプルは全てQDialogを継承したクラスで実装します。QDialogの使い方もクラスの使い方も今まで通りです。クラスを使うと同種の機能であるメソッドやプロパティがDialogクラスにまとめられるので、分別されて分かり易くなりますね。
QDialogクラスを継承したクラス
まずは、素のダイアログにラベル(QLabel)を貼り付けてみましょう。「create」メソッドで出てくる「layout」変数は、プロパティではなく単なる変数なので「self.」も付いていないし、createメソッド外では内容が保持されません。
・サンプルスクリプト「dlg_class.py」# モジュール from PyQt5.Qt import * from PyQt5.QtWidgets import QDialog, QHBoxLayout # ダイアログクラス class Dialog(QDialog): # ドキュメント作成 def create_doc(self,width,height): self.doc = Krita.instance().createDocument(width, height, "Line", "RGBA", "U8", "", 300.0) Krita.instance().activeWindow().addView(self.doc) # メイン処理 def create(self): self.create_doc(800,800) layout = QHBoxLayout() self.label = QLabel("ラベル") layout.addWidget(self.label) layout.setAlignment(self.label,Qt.AlignHCenter) self.setLayout(layout) # ダイアログ作成 dlg = Dialog() dlg.create() dlg.setWindowTitle("Dialog") dlg.resize(600,400) dlg.exec_()
【サンプルスクリプトの解説】
PyQt5内のモジュールを読み込みます。
QDialogクラスを継承したDialogクラスを宣言します。
「create_doc」メソッドはいつも通りです。
createメソッドでドキュメント作成を呼び出してレイアウトに中央寄せした“ラベル”文字列を貼り、レイアウトをダイアログにセットします。
Dialogクラスのインスタンスを生成して実行中(「exec_」メソッド)状態にします。
QDialogクラスを継承してランダムに円を描く
ダイアログにプッシュボタンを1個だけ配置し、これが押されるたびにランダムな位置にランダムな大きさの正円を描きます。正円の数は色相の数に合わせて360個で、正円は色相を0~360未満に変えた半透明の色です。
QPushButtonクラスのclickedのconnectメソッドでクリックして呼び出すフックをする場合も、関数だけでなくメソッドも登録できます。
・サンプルスクリプト「dlg_ellipse_class.py」# モジュール import random from PyQt5.Qt import * from PyQt5.QtWidgets import QDialog, QHBoxLayout, QPushButton # ダイアログクラス class Dialog(QDialog): (中略) # 円をランダムに描く def draw_ellipse(self): pixmap = QPixmap(self.doc.bounds().size()) pixmap.fill(QColor(Qt.transparent)) painter = QPainter() painter.begin(pixmap) painter.setRenderHint(QPainter.Antialiasing,True) for i in range(0,360): color = QColor.fromHsl(i, 255, 128, 96) pen = QPen(color) painter.setPen(pen) brush = QBrush(color) painter.setBrush(brush) x = random.randint(0,self.doc.width()) y = random.randint(0,self.doc.height()) r = random.randint(30,80) painter.drawEllipse(QPoint(x,y),r,r) painter.end() return pixmap.toImage() # ボタンが押されたら def click_button(self): self.img = self.draw_ellipse() self.set_layer() self.doc.refreshProjection() # レイヤーのセット def set_layer(self): root = self.doc.rootNode() layer = root.childNodes()[0] if self.img.sizeInBytes() == 4 * layer.channels()[0].channelSize() * self.doc.width() * self.doc.height(): ptr = self.img.bits() ptr.setsize(self.img.byteCount()) layer.setPixelData(QByteArray(ptr.asstring()), 0, 0, self.doc.width(), self.doc.height()) else: print('Error') # メイン処理 def create(self): self.create_doc(800,800) layout = QHBoxLayout() self.button = QPushButton("ランダムに円を描画し直す") layout.addWidget(self.button) self.button.clicked.connect(self.click_button) self.setLayout(layout) # ダイアログ作成 dlg = Dialog() dlg.create() dlg.exec_()
【サンプルスクリプトの解説】
乱数のモジュールやPyQt5内のモジュールやkritaのモジュールを読み込みます。
「draw_ellipse」メソッドでランダムに正円を描きます。QPenの輪郭もQBrushの塗り潰しも同じQColorの色です。
Dialog内のプッシュボタンが押されたら「click_button」メソッドが呼ばれます。
「set_layer」メソッドはいつも通りです。
createメソッドでドキュメントを作成し、レイアウトにプッシュボタンを配置します。プッシュボタンが押されると「click_button」メソッドが呼ばれ、レイアウトをダイアログにセットします。
Dialogクラスのインスタンスを生成し実行中状態にします。