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

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

QDialogクラスを継承したクラスのサンプル

これもQDialogを派生したクラスにUIパーツを貼り付けるサンプルです。QDialogクラスは継承させる例としてピッタリなクラスだと思います。ここに何を書こうか思案したのですが、博士論文や他の方が技術書を書くときも短い文に肉付けしていき原稿を仕上げていくそうなので、私も肉付けすることを肉付けしてみました。

QDialogクラスを継承して正方形をランダムに描く

UIパーツのスライダー(QSlider)をダイアログに貼り付けます。スライダーを操作すると、大きさが変化しながら、ランダムに1,080個の輪郭が描かれた色違いの白い正方形が描画されます。

ところで、サンプルスクリプトをそのままコピペするとエラーが出ると思います。当然(中略)のところでエラーが出ます。ここは前出のcreate_docメソッドとset_layerを省略しているので、これらをスクリプティングしてください。

図3:正方形をランダムに描く

・サンプルスクリプト「dlg_rect_class.py」
# モジュール
from PyQt5.Qt import *
import random
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog, QHBoxLayout,QLabel,QSlider
# ダイアログクラス
class Dialog(QDialog):
(中略)
  # スライダーが動いたら
  def set_value(self,value):
    self.label.setText(str(value))
    self.img = self.draw_rect(value)
    self.set_layer()
    self.doc.refreshProjection()
  # 正方形の描画
  def draw_rect(self,size):
    pixmap = QPixmap(self.doc.bounds().size())
    pixmap.fill(QColor(255,255,255,255))
    painter = QPainter()
    painter.begin(pixmap)
    for i in range(0,1080):
      color = QColor.fromHsl(0, 255, 255, 255)
      pen = QPen(color)
      painter.setPen(pen)
      color = QColor.fromHsl(i%360, 255, 128, 255)
      brush = QBrush(color)
      painter.setBrush(brush)
      x = random.randint(0,self.doc.width()-size)
      y = random.randint(0,self.doc.height()-size)
      painter.drawRect(x,y,size,size)
    painter.end()
    return pixmap.toImage()
(中略)
  # メイン処理
  def create(self):
    self.create_doc(800,800)
    layout = QHBoxLayout()
    self.label = QLabel("0") 
    layout.addWidget(self.label)
    self.slider = QSlider(Qt.Horizontal)
    layout.addWidget(self.slider)
    self.setLayout(layout)
    self.slider.valueChanged.connect(self.set_value)
# ダイアログ作成
dlg = Dialog()
dlg.create()
dlg.exec_()

【サンプルスクリプトの解説】
乱数のモジュールやPyQt5内のモジュールを読み込みます。
スライダーを移動させると「set_value」メソッドが呼ばれ、ラベルにスライダーの数値を表示して正方形を描きます。
「draw_rect」メソッドでランダムに1,080個の正方形を色相を変えて描画します。正方形の1辺の長さはスライダーで指定した長さになります。
「create」メソッドでドキュメントを作成し、ラベルとスライダーをレイアウトに配置してレイアウトをダイアログにセットします。スライダーの値が変化したら「set_value」メソッドをフックします。
Dialogクラスのインスタンスを生成し実行中(「exec_」メソッド)状態にします。

QDialogクラスを継承してフォントを選ぶ

第7回では「フォント選択ダイアログ(QFontDialog)」を使いましたが、今回は「フォントコンボボックス(QFontComboBox)」を使います。後者はQDialogにUIパーツとして貼り付けることができます。また前者のようにフォントサイズなどは選択できず、後者はフォント名のみ選択できます。

描画する文字は「ラインエディット(QLineEdit)」に任意の文字を入力すれば、フォント名を変更したときにキャンバスに描画されます。

図4:文字を入力し、フォントを選ぶ

・サンプルスクリプト「dlg_font_class.py」
# モジュール
from PyQt5.Qt import *
from PyQt5.QtWidgets import QDialog,QFormLayout,QLineEdit,QFontComboBox
import random
# ダイアログクラス
class Dialog(QDialog):
(中略)
  # 画像の描画
  def draw_img(self,value):
    self.font = QFont(value)
    self.font.setPointSizeF(32)
    self.img = self.draw_font(self.edit.text())
    self.set_layer()
    self.doc.refreshProjection()
  # フォントの描画
  def draw_font(self,text):
    painter = QPainter()
    painter.begin(self.pixmap)
    x = random.randint(0,self.doc.width()-400)
    y = random.randint(32,self.doc.height()-32)
    try:
      painter.setFont(self.font)
      painter.drawText(QPointF(x,y),text)
    finally:
      painter.end()
    return self.pixmap.toImage()
(中略)
  # メイン処理
  def create(self):
    self.create_doc(800,800)
    layout = QFormLayout()
    self.edit = QLineEdit("文字を入力してください。")
    layout.addWidget(self.edit)
    self.fontcombo = QFontComboBox()
    layout.addWidget(self.fontcombo)
    self.setLayout(layout)
    self.fontcombo.currentFontChanged.connect(self.draw_img)
    self.pixmap = QPixmap(self.doc.bounds().size())
    self.pixmap.fill(QColor(255,255,255))
# ダイアログの作成
dlg = Dialog()
dlg.create()
dlg.exec_()

【サンプルスクリプトの解説】
PyQt5内のモジュールを読み込みます。
「draw_img」メソッドで指定したフォントで文字を描画する「draw_font」メソッドを呼び出し、レイヤーをセットして描画します。
「draw_font」メソッドでラインエディットに書かれた文字をランダムな位置に描画します。
「create」メソッドでドキュメントを作成し、ラインエディットとフォントコンボボックスをレイアウトに配置してレイアウトをセットします。フォントコンボボックスのフォントが変更されたときに呼び出す「draw_img」メソッドをフックします。「pixmap」プロパティにイメージを描く用意をします。
Dialogクラスのインスタンスを生成し実行中(「exec_」メソッド)状態にします。

おわりに

今回は、QDialogを継承したDialogクラスを実装し、クラスを利用する例を紹介しました。クラスを使用することで、ダイアログにUIパーツを貼り付ける処理が整理され、スクリプトを見たときに判読しやすくなりました。

著者
大西 武 (オオニシ タケシ)
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メルマガ会員のサービス内容を見る

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