「Krita」と「Python」のクラスでダイアログを使ってみよう

2025年1月30日(木)
大西 武 (オオニシ タケシ)
第12回の今回は「Krita」の「Python」でクラスを使ってダイアログ(QDialog)を継承し、UIを構築する解説をします。

はじめに

今回は第8回で解説した、ダイアログ(QDialog)に付けるUIパーツなどをクラスを継承してプログラミングします。QDialogクラスを継承した「Dialog」クラスを宣言することで、Dialogクラス内でQDialogクラスのメソッドやプロパティが「self.」を付けて使えます。

今回用意したのは「素のダイアログ(QDialog)」「ラベル(QLabel)」「プッシュボタン(QPushButton)」「スライダー(QSlider)」「ラインエディット(QLineEdit)」「フォントコンボボックス(QFontComboBox)」を使ったサンプルです。「フォントコンボボックス(QFontComboBox)」だけ新たに解説しますが、これまでと同様に操作すれば簡単に実装できます。

素のダイアログを継承したクラスを使う

今回のサンプルは全てQDialogを継承したクラスで実装します。QDialogの使い方もクラスの使い方も今まで通りです。クラスを使うと同種の機能であるメソッドやプロパティがDialogクラスにまとめられるので、分別されて分かり易くなりますね。

QDialogクラスを継承したクラス

まずは、素のダイアログにラベル(QLabel)を貼り付けてみましょう。「create」メソッドで出てくる「layout」変数は、プロパティではなく単なる変数なので「self.」も付いていないし、createメソッド外では内容が保持されません。

図1:素のダイアログ

・サンプルスクリプト「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メソッドでクリックして呼び出すフックをする場合も、関数だけでなくメソッドも登録できます。

図2:ボタンを押すごとにランダムに正円を描く

・サンプルスクリプト「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クラスのインスタンスを生成し実行中状態にします。

著者
大西 武 (オオニシ タケシ)
1975年香川県生まれ。大阪大学経済学部経営学科中退。プログラミング入門書など30冊以上を商業出版する作家。Microsoftで大賞やNTTドコモでグランプリなど20回以上全国区のコンテストに入賞するアーティスト。オリジナルの間違い探し「3Dクイズ」が全国放送のTVで約10回出題。
https://profile.vixar.jp

連載バックナンバー

開発言語技術解説
第12回

「Krita」と「Python」のクラスでダイアログを使ってみよう

2025/1/30
第12回の今回は「Krita」の「Python」でクラスを使ってダイアログ(QDialog)を継承し、UIを構築する解説をします。
開発言語技術解説
第11回

「Krita」と「Python」のクラスでアニメーション動画を作ろう

2025/1/10
第11回の今回は「Krita」と「Python」のクラスを使ってアニメーションする動画を作る解説をします。
開発言語技術解説
第10回

「Krita」と「Python」のクラスで画像を加工しよう

2024/12/13
第10回の今回は「Krita」で「Python」のクラスを使ってプログラミングして、開いた画像ファイルに擦りガラス加工などをする解説をします。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています