Pythonを使ってペイントアプリケーションを構築する方法

シンプルなペイントツールは、ほとんどのコンピュータで最もよく見られるアプリの1つです。アーティストは失敗を恐れることなく間違いを犯すことができ、ボタンをクリックするだけで任意の色を選択し、ブラシのストロークのサイズを即座に変更できます。これを使ってブランドロゴを作成したり、ユーザーインターフェイスを概念化したり、図に注釈を付けたりすることができます。

では、ペイントアプリケーションを構築するにはどうすればよいでしょうか?

TkinterとPillowモジュール

ペイントアプリケーションを構築するには、TkinterとPillowモジュールが必要です。Tkinterは、GUIをカスタマイズするために使用できる最高のPythonフレームワークの1つです。デスクトップアプリケーションを作成するための標準的なPython GUIモジュールです。Tkinterには、ラベル、エントリ、キャンバス、ボタンなどのさまざまなウィジェットが付属しています。

Python Imaging Library (PIL) のフォークであるPillowは、Python用の画像処理モジュールです。Pillowを使用すると、画像を開いたり、サイズを変更したり、反転したり、トリミングしたりできます。ファイル形式を変換したり、レシピファインダーアプリケーションを構築したり、ランダムな画像を取得したりできます。

これらのモジュールをインストールするには、次を実行します:

pip install tk pillow

ペイントアプリケーションの構造を定義する

このプロジェクトのソースコード全体は、このGitHubリポジトリにあります。

必要なモジュールをインポートすることから始めます。クラスDrawAppを定義します。タイトル、ポインタの色、消しゴムの色を設定します。アプリケーションを全画面で開きます。setup_widgetsメソッドを呼び出します。

import tkinter as tk
from tkinter.ttk import Scale
from tkinter import colorchooser, filedialog, messagebox
import PIL.ImageGrab as ImageGrab
class DrawApp:
def __init__(self, root):
self.root = root
self.root.title("Kids' Paint App")
self.root.attributes("-fullscreen", True)
self.pointer = "black"
self.erase = "white"
self.setup_widgets()

setup_widgetsというメソッドを定義します。見出しを表示するラベルを定義します。親要素、表示するテキスト、フォントスタイル、背景色、テキストの色を設定します。カラーパレットのフレームを定義します。親要素、表示するテキスト、フォントスタイル、ボーダーの幅を設定します。ボーダーをリッジのような外観にし、背景色を白にします。

def setup_widgets(self):
self.title_label = tk.Label(
self.root,
text="Kids' Paint App",
font=("Comic Sans MS", 30),
bg="lightblue",
fg="purple",
)
self.title_label.pack(fill=tk.X, pady=10)
self.color_frame = tk.LabelFrame(
self.root,
text="Colors",
font=("Comic Sans MS", 15),
bd=5,
relief=tk.RIDGE,
bg="white",
)
self.color_frame.place(x=10, y=80, width=90, height=180)

リスト内のカラーパレットの色を定義します。それを反復処理して、それぞれにボタンを作成します。親要素、背景色、ボーダーの幅、外観を設定します。各ボタンがクリックされたときに実行する幅とコマンドも設定します。すべて要素を適切なパディングと色を2つずつセットで整理します。

colors = [
"blue",
"red",
"green",
"orange",
"violet",
"black",
"yellow",
"purple",
"pink",
"gold",
"brown",
"indigo",
]
i, j = 0, 0
for color in colors:
tk.Button(
self.color_frame,
bg=color,
bd=2,
relief=tk.RIDGE,
width=3,
command=lambda col=color: self.select_color(col),
).grid(row=i, column=j, padx=2, pady=2)
i += 1
if i == 4:
i = 0
j = 1

同様に、消しゴム、画面をクリアするボタン、画像を保存するボタンを定義します。

self.eraser_btn = tk.Button(
self.root,
text="Eraser",
bd=4,
bg="white",
command=self.eraser,
width=9,
relief=tk.RIDGE,
font=("Comic Sans MS", 12),
)
self.eraser_btn.place(x=10, y=310)
self.clear_screen_btn = tk.Button(
self.root,
text="Clear Screen",
bd=4,
bg="white",
command=self.clear_screen,
width=12,
relief=tk.RIDGE,
font=("Comic Sans MS", 12),
)
self.clear_screen_btn.place(x=10, y=370)
self.save_as_btn = tk.Button(
self.root,
text="Save Drawing",
bd=4,
bg="white",
command=self.save_as,
width=12,
relief=tk.RIDGE,
font=("Comic Sans MS", 12),
)
self.save_as_btn.place(x=10, y=430)
self.bg_btn = tk.Button(
self.root,
text="Background",
bd=4,
bg="white",
command=self.canvas_color,
width=12,
relief=tk.RIDGE,
font=("Comic Sans MS", 12),
)
self.bg_btn.place(x=10, y=490)
self.pointer_frame = tk.LabelFrame(
self.root,
text="Size",
bd=5,
bg="white",
font=("Comic Sans MS", 15, "bold"),
relief=tk.RIDGE,
)

ポインタまたは消しゴムのサイズを大きくしたり小さくしたりするためのスケールウィジェットを定義します。親要素、向き、範囲、ピクセル単位の長さを設定します。キャンバスを定義し、親要素、背景色、ボーダーの幅を設定します。また、リリーフをその高さおよび幅とともに溝状の外観になるように設定します。

キャンバスを適切な座標で配置し、アンカーを北西(左上)に設定します。B1-Motionをペイント機能にバインドします。B1は押したままの左マウスボタンを指し、Motionは動きを指します。全体として、左ボタンを押しながらマウスの動きを追跡するために使用します。

self.pointer_frame.place(x=10, y=580, height=150, width=70)
self.pointer_size = Scale(
self.pointer_frame, orient=tk.VERTICAL, from_=48, to=1, length=120
)
self.pointer_size.set(1)
self.pointer_size.grid(row=0, column=1, padx=15)
self.canvas = tk.Canvas(
self.root, bg="white", bd=5, relief=tk.GROOVE, height=650, width=1300
)
self.canvas.place(x=160, y=120, anchor="nw")
self.canvas.bind("<B1-Motion>", self.paint)

ペイントアプリケーションの機能を定義する

paintというメソッドを定義します。ペイントするには、アプリは小さな楕円を連続的に描画します。マウスイベントのx座標とy座標から2を引いて、楕円の左上隅を決定します。楕円の右下隅を決定するには2を加えます。これらの境界座標を使用して楕円を作成します。

ポインタを選択した内容に従って、塗りつぶしの色、輪郭の色、幅を設定します。

def paint(self, event):
x1, y1 = (event.x - 2), (event.y - 2)
x2, y2 = (event.x + 2), (event.y + 2)
self.canvas.create_oval(
x1,
y1,
x2,
y2,
fill=self.pointer,
outline=self.pointer,
width=self.pointer_size.get(),
)

select_coloreraserclear_screenの3つの関数を定義します。select_colorメソッドは色を取得し、それに応じてポインタを設定します。eraserメソッドはポインタに消しゴムのような効果を持たせ、透明な線を描画します。clear_screenメソッドはキャンバス上のすべてのアイテムを削除します。

def select_color(self, col):
self.pointer = col
def eraser(self):
self.pointer = self.erase
def clear_screen(self):
self.canvas.delete("all")

canvas_colorというメソッドを定義します。さまざまな色をすべて備えたカラーパレットを開きます。RGB形式と16進形式で色を含むタプルを返します。ユーザーが色を選択した場合、configureメソッドを使用して背景色を設定します。消しゴムの色を背景色と同じに設定します。

def canvas_color(self):
color = colorchooser.askcolor()
if color:
self.canvas.configure(background=color[1])
self.erase = color[1]

save_asというメソッドを定義します。ユーザーにファイル名とパスを選択するよう求めるファイルダイアログボックスを開きます。ユーザーがパスを選択した場合、PillowのImageGrabクラスを使用して画面全体をキャプチャします。指定した座標を使用して画像を切り取り、キャンバス領域を取得します。目的の部分を取得するために座標を試行します。

この結果を目的のファイルパスに保存します。プログラムがペイントを画像として正常に保存したことをユーザーに通知するメッセージボックスを表示します。エラーが発生した場合は、対応するエラーを表示します。

def save_as(self):
file_path = filedialog.asksaveasfilename(
defaultextension=".jpg", filetypes=[("Image files", "*.jpg")]
)
if file_path:
try:
y = 148
x = 200
y1 = 978
x1 = 1840
ImageGrab.grab().crop((x, y, x1, y1)).save(file_path)
messagebox.showinfo("Save Drawing", "Image file saved successfully!")
except Exception as e:
messagebox.showerror("Error", f"Failed to save the image file: {e}")

TkDrawAppクラスのインスタンスを作成します。mainloop()関数は、PythonにTkinterイベントループを実行し、ウィンドウを閉じるまでイベントをリッスンするように指示します。

if __name__ == "__main__":
root = tk.Tk()
app = DrawApp(root)
root.mainloop()

Pythonを使用してさまざまなペイント機能をテストする

ペイントプログラムを実行すると、カラーパレット、4つのボタン、1つのスライダー、ペイント用のキャンバスを備えたアプリが表示されます:

色をクリックして選択します。その後、左マウスボタンでその色でキャンバスに描画できます:

消しゴムボタンをクリックし、スライダーを垂直に上にドラッグすると、消しゴムを選択してサイズを大きくすることができます。消しゴムを図の上でドラッグして、ストロークを消去して、消しゴムをテストします。

画面をクリアボタンをクリックすると、プログラムは前の図をクリアします。背景ボタンをクリックしてカラーパレットを開き、それを使用して背景色を変更します。

図面を保存ボタンをクリックすると、ファイルダイアログボックスが開きます。ファイルのパスと名前を選択すると、プログラムが保存します。

ペイントアプリケーションの強化

図形を追加するオプションを追加することで、ペイントアプリケーションの機能を強化できます。ブラシの種類と不透明度を選択するオプションを提供できます。テキストとステッカーを追加するオプションを追加します。元に戻す、やり直し、サイズ変更、画像の反転のオプションを追加します。これにより、描画プロセスがはるかにスムーズになります。

図形を作成するには、create_rectangle、create_oval、create_line、create_polygonなどのメソッドを使用できます。テキストと画像を追加するには、create_textとcreate_imageメソッドを使用します。画像のサイズを変更したり反転したりするには、Pillowのresizeとtransposeメソッドを使用できます。