「Krita」と「Python」でダイアログUIを構築してみよう

2024年10月11日(金)
大西 武 (オオニシ タケシ)
第7回の今回は「Krita」の「Python」で「PyQt5」モジュールの「ウィジェット」を使って、ダイアログUIを構築する解説をします。

フォント選択ダイアログ

最後にフォント選択ダイアログを解説します。「フォント」とは「字体」という意味で、字の形の種類のことです。

まず、フォント選択ダイアログでフォント名を取得します。ここまではシンプルなダイアログの使い方のみでしたが、さらに第5回のフォントを表示するサンプルと組み合わせて、フォント選択ダイアログで選んだフォントで文字を書きます。

フォント選択ダイアログでフォントを選ぶ

フォントを選べるフォント選択ダイアログ(図6)を解説します。フォント選択ダイアログでは、フォント名を選ぶだけでなく、文字の太さを選べたり、フォントサイズを選べたり、取り消し線や下線を選べたり、日本語などの言語を選べたりします。

図6:フォント選択ダイアログ

・サンプルスクリプト「dlg_font.py」
# モジュール
from PyQt5.QtWidgets import QFontDialog
# フォント選択ダイアログ
font = QFontDialog.getFont()
if font[1] == True:
  print(font[0].toString())
else:
  print("フォントが指定されていません")

【サンプルスクリプトの解説】
「PyQt5.QtWidgets」モジュールの「QFontDialog」モジュールを読み込みます。
フォント選択ダイアログを表示し、選んだフォント名をコンソールに表示します。

フォント選択ダイアログで選んだフォントで文字を書く

ここまではダイアログの使い方しか解説してきませんでしたが、最後にダイアログを使った応用例を解説します。ここではフォント選択ダイアログ(図7)で選んだフォントで“明日はきっと株価が上がる”という文字列をドキュメントのレイヤーに書きます。

先ほどの「dlg_font.py」ファイルと第5回の「font.py」ファイルを組み合わせただけみたいなものです。

図7:フォント選択ダイアログで選んだフォントで文字を書く

・サンプルスクリプト「dlg_font_demo.py」
# モジュール
from PyQt5.Qt import *
from PyQt5.QtWidgets import QFontDialog
# ドキュメントの作成
def create_doc(width,height):
  doc = Krita.instance().createDocument(width,height, "Document name", "RGBA", "U8", "", 300.0)
  Krita.instance().activeWindow().addView(doc)
  return doc
# 描画
def draw_fukidashi(doc):
  pixmap = QPixmap(doc.bounds().size())
  pixmap.fill(QColor(255,255,255))
  painter = QPainter()
  painter.begin(pixmap)
  painter.setRenderHint(QPainter.Antialiasing,True)
  color = QColor(0, 0, 0, 255)
  pen = QPen(color)
  pen.setWidth(4)
  painter.setPen(pen)
  color = QColor(255, 255, 255, 255)
  brush = QBrush(color)
  painter.setBrush(brush)
  draw_font(painter)
  painter.end()
  return pixmap.toImage()
# 文字列描画
def draw_font(painter):
  # フォント選択ダイアログ
  font = QFontDialog.getFont()
  try:
    painter.setFont(font[0])
    painter.drawText(QPointF(50,300),"明日はきっと株価が上がる")
  finally:
    painter.end()
# レイヤーのセット
def set_layer(doc,img):
  # 修正箇所
  root = doc.rootNode()
  # 修正箇所
  layer = root.childNodes()[0]
  # レイヤーに画像をセット
  if img.sizeInBytes() == 4 * layer.channels()[0].channelSize() *  doc.width() * doc.height():
    ptr = img.bits()
    ptr.setsize(img.byteCount())
    layer.setPixelData(QByteArray(ptr.asstring()), 0, 0, doc.width() , doc.height()) 
  else:
    print('Error')
# メイン関数
def begin_draw():
  doc = create_doc(800,800)
  img = draw_fukidashi(doc)
  set_layer(doc,img)
  doc.refreshProjection()
# メイン関数の呼び出し
begin_draw()

【サンプルスクリプトの解説】
「PyQt5.Qt」モジュールの全て(*)と「PyQt5.QtWidgets」モジュールの「QFontDialog」モジュールを読み込みます。
「create_doc」関数と「begin_draw」関数はいつものように同じです。
「draw_fukidashi」関数で色を用意して「draw_font」関数を呼び出し、フォント選択ダイアログで選んだフォントで文字列を書きます。
「set_layer」関数は、いつもとは違い少し修正しなければなりません(コラム参照)。

【コラム】「Krita 5.2.3」でのPythonのモジュールの不具合

今年初めてのKritaのバージョンアップで「5.2.3」になりましたが、これまでの連載で解説してきたサンプルスクリプトの一部が動作しなくなりました。Krita連載の第3回~第5回のサンプルスクリプトの以下の1行を以下の2行に書き換えてください。

「activeNode」でアクティブなレイヤーを取得する代わりに、ルートノードの最初の子レイヤーを取得して「layer」変数に代入します。「activeNode」メソッド自体はエラーにならないのですが、どうやらデフォルトのレイヤーがアクティブな状態でなくなって取得できないようです。

恐らく今後のバージョンアップで改善されると思います。

・Krita連載の第3回~第5回のサンプルスクリプトの修正点(インデントに気を付けてください)
修正前
layer = doc.activeNode()
↓
修正後
root = doc.rootNode()
layer = root.childNodes()[0]

おわりに

今回は、Kritaで使える「PyQt5」モジュールのUI機能である「Widget(ウィジェット)」の中でもダイアログのみ解説をしました。次回はダイアログに貼り付けるボタンやスライダーなどのUIウィジェットの使い方について解説します。

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

連載バックナンバー

開発言語技術解説
第7回

「Krita」と「Python」でダイアログUIを構築してみよう

2024/10/11
第7回の今回は「Krita」の「Python」で「PyQt5」モジュールの「ウィジェット」を使って、ダイアログUIを構築する解説をします。
開発言語技術解説
第6回

「Krita」と「Python」でアニメーションを描いてみよう

2024/9/24
第6回の今回は「Krita」で「Python」をプログラミングして、正方形が回転するアニメーションを作成する解説をします。
開発言語技術解説
第5回

「Krita」と「Python」で「ベジェ曲線」を描いてみよう

2024/9/5
第5回の今回は「Krita」でベジェ曲線のフキダシを描いたり、指定したフォントで文字を書いたりする解説をします。

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

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

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

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