GUI

[Python/Tkinter] Canvasの使い方 – 画像や図形の描画

PythonのTkinterライブラリのCanvasウィジェットは、画像や図形を描画するための領域を提供します。

Canvasでは、直線、矩形、楕円、ポリゴンなどの図形を描画でき、create_linecreate_rectanglecreate_ovalなどのメソッドを使用します。

また、create_imageメソッドを使って画像を表示することも可能です。

画像を表示する際は、PIL(Pillow)ライブラリを使って画像を読み込み、TkinterのPhotoImageオブジェクトとしてCanvasに渡します。

Canvasとは

Canvasは、PythonのTkinterライブラリに含まれるウィジェットの一つで、2Dグラフィックスを描画するための領域を提供します。

Canvasを使用することで、直線や矩形、楕円、多角形などの基本的な図形を描くことができ、さらに画像を表示したり、テキストを描画したりすることも可能です。

Canvasは、インタラクティブなアプリケーションやゲームの開発において非常に便利なツールです。

Canvasの主な特徴は、以下の通りです:

  • 描画機能: さまざまな図形や画像を描画できる。
  • イベント処理: マウスやキーボードの入力に応じて動的に描画を変更できる。
  • 座標系: 左上を原点とした座標系を使用し、オブジェクトの位置を簡単に管理できる。

このように、Canvasは視覚的な要素を扱う際に非常に強力なツールであり、Pythonプログラミングにおいて多くの可能性を秘めています。

図形の描画

TkinterのCanvasを使用すると、さまざまな図形を簡単に描画できます。

以下では、基本的な図形の描き方を紹介します。

直線を描く(create_line)

直線を描くには、create_lineメソッドを使用します。

このメソッドは、始点と終点の座標を指定することで直線を描画します。

import tkinter as tk
def draw_line(canvas):
    canvas.create_line(10, 10, 200, 10, fill="blue", width=2)
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
draw_line(canvas)
root.mainloop()
青い直線が描画される

矩形を描く(create_rectangle)

矩形を描くには、create_rectangleメソッドを使用します。

左上と右下の座標を指定することで矩形を描画します。

import tkinter as tk
def draw_rectangle(canvas):
    canvas.create_rectangle(50, 50, 150, 100, fill="red", outline="black")
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
draw_rectangle(canvas)
root.mainloop()
赤い矩形が描画される

楕円を描く(create_oval)

楕円を描くには、create_ovalメソッドを使用します。

矩形の外接矩形を指定することで楕円を描画します。

import tkinter as tk
def draw_oval(canvas):
    canvas.create_oval(70, 70, 125, 150, fill="green", outline="black")
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
draw_oval(canvas)
root.mainloop()
緑の楕円が描画される

多角形を描く(create_polygon)

多角形を描くには、create_polygonメソッドを使用します。

各頂点の座標を指定することで多角形を描画します。

import tkinter as tk
def draw_polygon(canvas):
    canvas.create_polygon(100, 50, 150, 100, 50, 100, fill="yellow", outline="black")
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
draw_polygon(canvas)
root.mainloop()
黄色の三角形が描画される

テキストを描く(create_text)

テキストを描くには、create_textメソッドを使用します。

表示する位置とテキスト内容を指定することで、Canvas上にテキストを描画します。

import tkinter as tk
def draw_text(canvas):
    canvas.create_text(150, 100, text="こんにちは", font=("Arial", 20), fill="black")
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
draw_text(canvas)
root.mainloop()
「こんにちは」というテキストが描画される

図形の色や線の太さを変更する方法

図形の色や線の太さは、各描画メソッドの引数で指定できます。

fill引数で内部の色を、outline引数で外枠の色を、width引数で線の太さを設定します。

以下は、矩形の色と線の太さを変更する例です。

import tkinter as tk
def draw_custom_rectangle(canvas):
    canvas.create_rectangle(50, 50, 150, 100, fill="purple", outline="white", width=3)
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
draw_custom_rectangle(canvas)
root.mainloop()
紫色の矩形が白い外枠で描画される

このように、Canvasを使うことで簡単にさまざまな図形を描画し、色や線のスタイルを変更することができます。

画像の描画

TkinterのCanvasを使用すると、画像を簡単に表示することができます。

以下では、画像の描画方法や、Pillowライブラリを使った画像の操作について説明します。

画像をCanvasに表示する(create_image)

画像をCanvasに表示するには、create_imageメソッドを使用します。

このメソッドでは、画像の位置を指定し、表示する画像を指定します。

import tkinter as tk
from PIL import Image, ImageTk
def draw_image(canvas):
    image = Image.open("example.png")  # 画像ファイルを指定
    photo = ImageTk.PhotoImage(image)   # Tkinter用に変換
    canvas.create_image(150, 100, image=photo)  # 画像をCanvasに表示
    canvas.image = photo  # 参照を保持するために必要
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
draw_image(canvas)
root.mainloop()
指定した画像がCanvasに表示される

Pillowライブラリを使った画像の読み込み

Pillowライブラリを使用すると、さまざまな形式の画像を簡単に読み込むことができます。

以下は、Pillowを使ってJPEG画像を読み込む例です。

import tkinter as tk
from PIL import Image, ImageTk
def load_image(canvas):
    image = Image.open("example.jpg")  # JPEG画像を指定
    photo = ImageTk.PhotoImage(image)   # Tkinter用に変換
    canvas.create_image(150, 100, image=photo)
    canvas.image = photo
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
load_image(canvas)
root.mainloop()
指定したJPEG画像がCanvasに表示される

画像のサイズ変更や位置調整

画像のサイズを変更するには、Pillowライブラリのresizeメソッドを使用します。

以下は、画像を指定したサイズに変更して表示する例です。

import tkinter as tk
from PIL import Image, ImageTk
def resize_image(canvas):
    image = Image.open("example.png")
    resized_image = image.resize((100, 100))  # 100x100ピクセルにリサイズ
    photo = ImageTk.PhotoImage(resized_image)
    canvas.create_image(150, 100, image=photo)
    canvas.image = photo
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
resize_image(canvas)
root.mainloop()
リサイズされた画像がCanvasに表示される

画像の削除や更新

Canvas上の画像を削除するには、deleteメソッドを使用します。

画像を更新する場合は、古い画像を削除して新しい画像を追加します。

以下は、画像を削除して新しい画像を表示する例です。

import tkinter as tk
from PIL import Image, ImageTk
def update_image(canvas):
    # 古い画像を削除
    canvas.delete("all")
    
    # 新しい画像を読み込む
    new_image = Image.open("new_example.png")
    photo = ImageTk.PhotoImage(new_image)
    canvas.create_image(150, 100, image=photo)
    canvas.image = photo
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
update_image(canvas)
root.mainloop()
新しい画像がCanvasに表示される

このように、TkinterのCanvasを使用することで、画像の表示、サイズ変更、位置調整、削除や更新が簡単に行えます。

Pillowライブラリを併用することで、より多様な画像操作が可能になります。

イベント処理とCanvas

TkinterのCanvasでは、ユーザーの操作に応じて動的に描画を変更することができます。

以下では、マウスクリックやキーボード入力を使ったイベント処理の方法を紹介します。

マウスクリックで図形を描画する

マウスクリックイベントを利用して、クリックした位置に図形を描画することができます。

以下は、マウスクリックで矩形を描画する例です。

import tkinter as tk
def draw_rectangle(event):
    x, y = event.x, event.y  # クリックした位置の座標を取得
    canvas.create_rectangle(x-20, y-20, x+20, y+20, fill="blue")
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
canvas.bind("<Button-1>", draw_rectangle)  # 左クリックで矩形を描画
root.mainloop()
クリックした位置に青い矩形が描画される

キーボード入力でCanvasを操作する

キーボード入力を使ってCanvas上のオブジェクトを操作することも可能です。

以下は、特定のキーを押すことで図形を移動する例です。

import tkinter as tk
def move_rectangle(event):
    if event.keysym == "Up":
        canvas.move(rectangle, 0, -10)  # 上に移動
    elif event.keysym == "Down":
        canvas.move(rectangle, 0, 10)   # 下に移動
    elif event.keysym == "Left":
        canvas.move(rectangle, -10, 0)  # 左に移動
    elif event.keysym == "Right":
        canvas.move(rectangle, 10, 0)   # 右に移動
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
rectangle = canvas.create_rectangle(100, 100, 150, 150, fill="red")  # 矩形を描画
canvas.bind("<Key>", move_rectangle)  # キー入力をバインド
canvas.focus_set()  # Canvasにフォーカスを設定
root.mainloop()
矢印キーで赤い矩形を移動できる

図形や画像のドラッグ&ドロップ

Canvas上の図形や画像をドラッグ&ドロップで移動することもできます。

以下は、図形をドラッグして移動する例です。

import tkinter as tk
def start_drag(event):
    global offset_x, offset_y
    offset_x = event.x
    offset_y = event.y
def drag(event):
    x = event.x - offset_x
    y = event.y - offset_y
    canvas.move(rectangle, x, y)  # 矩形を移動
    global offset_x, offset_y
    offset_x = event.x
    offset_y = event.y
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
rectangle = canvas.create_rectangle(100, 100, 150, 150, fill="green")  # 矩形を描画
canvas.tag_bind(rectangle, "<Button-1>", start_drag)  # クリックでドラッグ開始
canvas.tag_bind(rectangle, "<B1-Motion>", drag)  # ドラッグ中の動作
root.mainloop()
緑の矩形をドラッグして移動できる

Canvas上のオブジェクトに対するイベントバインディング

Canvas上のオブジェクトに対して、特定のイベントをバインドすることができます。

以下は、矩形をクリックしたときに色を変更する例です。

import tkinter as tk
def change_color(event):
    canvas.itemconfig(rectangle, fill="yellow")  # 矩形の色を変更
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
rectangle = canvas.create_rectangle(100, 100, 150, 150, fill="purple")  # 矩形を描画
canvas.tag_bind(rectangle, "<Button-1>", change_color)  # クリックで色を変更
root.mainloop()
紫色の矩形をクリックすると黄色に変わる

このように、TkinterのCanvasでは、マウスやキーボードの入力に応じて動的に描画を変更することができ、インタラクティブなアプリケーションを作成することが可能です。

イベント処理を活用することで、ユーザーとの対話をより豊かにすることができます。

Canvasの座標系

TkinterのCanvasでは、描画する際の座標系が重要な役割を果たします。

ここでは、Canvasの座標系の基本や、座標を使った操作について説明します。

座標系の基本(左上原点)

Canvasの座標系は、左上を原点(0, 0)とし、右方向にx座標が増加し、下方向にy座標が増加します。

これにより、Canvas上の位置を簡単に指定できます。

以下は、座標系の例です。

  • 原点: (0, 0)
  • 右方向: x座標が増加
  • 下方向: y座標が増加
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
canvas.create_text(150, 20, text="原点(0, 0)", font=("Arial", 12))
canvas.create_rectangle(50, 50, 100, 100, fill="blue")  # 矩形を描画
canvas.create_text(75, 75, text="(50, 50)", fill="white")  # 矩形の中心にテキスト
root.mainloop()
青い矩形が(50, 50)に描画される

座標の変換とスクロール

Canvasでは、座標の変換やスクロールを行うことができます。

moveメソッドを使用して、オブジェクトを指定した距離だけ移動させることができます。

また、xviewyviewメソッドを使って、Canvasの表示領域をスクロールすることも可能です。

import tkinter as tk
def scroll_canvas(event):
    canvas.xview_scroll(-1 if event.keysym == "Left" else 1, "units")
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200, scrollregion=(0, 0, 600, 200))
canvas.pack()
canvas.create_rectangle(0, 0, 600, 200, fill="lightgray")  # スクロール領域を設定
canvas.create_rectangle(100, 50, 200, 150, fill="red")  # 矩形を描画
canvas.bind("<Left>", scroll_canvas)  # 左キーでスクロール
canvas.bind("<Right>", scroll_canvas)  # 右キーでスクロール
root.mainloop()
左または右キーでCanvasをスクロールできる

座標を使った図形の移動

Canvas上の図形を移動するには、moveメソッドを使用します。

以下は、矩形をクリックした位置に移動させる例です。

import tkinter as tk
def move_rectangle(event):
    canvas.coords(rectangle, event.x - 25, event.y - 25, event.x + 25, event.y + 25)  # 矩形を移動
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
rectangle = canvas.create_rectangle(100, 100, 150, 150, fill="green")  # 矩形を描画
canvas.bind("<Button-1>", move_rectangle)  # クリックで矩形を移動
root.mainloop()
クリックした位置に緑の矩形が移動する

座標を使った衝突判定

Canvas上での衝突判定は、オブジェクトの座標を使って行います。

以下は、矩形が他の矩形と衝突しているかを判定する例です。

import tkinter as tk
def check_collision(event):
    x1, y1, x2, y2 = canvas.coords(rectangle)  # 矩形の座標を取得
    if (50 < x1 < 150 and 50 < y1 < 150) or (50 < x2 < 150 and 50 < y2 < 150):
        print("衝突しました!")  # 衝突判定
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
rectangle = canvas.create_rectangle(100, 100, 150, 150, fill="blue")  # 矩形を描画
canvas.create_rectangle(50, 50, 200, 200, outline="red")  # 衝突判定用の矩形
canvas.bind("<Button-1>", check_collision)  # クリックで衝突判定
root.mainloop()
衝突した場合、コンソールに「衝突しました!」と表示される

このように、Canvasの座標系を理解することで、図形の描画や移動、衝突判定などの操作が可能になります。

座標系を活用することで、よりインタラクティブなアプリケーションを作成することができます。

Canvasの応用例

TkinterのCanvasは、さまざまなアプリケーションに応用できます。

以下では、具体的な応用例をいくつか紹介します。

ゲームの作成(簡単なブロック崩し)

Canvasを使って、シンプルなブロック崩しゲームを作成することができます。

以下は、ボールを動かしてブロックを壊す基本的なゲームの例です。

import tkinter as tk

class BlockBreaker:
    def __init__(self, root):
        self.canvas = tk.Canvas(root, width=400, height=300)
        self.canvas.pack()
        self.ball = self.canvas.create_oval(190, 150, 210, 170, fill="red")
        self.paddle = self.canvas.create_rectangle(170, 250, 230, 260, fill="blue")
        self.blocks = [self.canvas.create_rectangle(x, 50, x+40, 70, fill="green") for x in range(0, 400, 50)]
        self.dx = 2
        self.dy = -2
        self.move_ball()
        self.canvas.bind("<Motion>", self.move_paddle)

    def move_ball(self):
        self.canvas.move(self.ball, self.dx, self.dy)
        x1, y1, x2, y2 = self.canvas.coords(self.ball)
        if x1 <= 0 or x2 >= 400:
            self.dx = -self.dx
        if y1 <= 0:
            self.dy = -self.dy
        if y2 >= 300:
            self.dy = -self.dy  # ボールが下に落ちた場合の処理
        self.check_collision()
        self.canvas.after(20, self.move_ball)

    def move_paddle(self, event):
        self.canvas.coords(self.paddle, event.x - 30, 250, event.x + 30, 260)

    def check_collision(self):
        ball_coords = self.canvas.coords(self.ball)
        
        # パドルとの衝突判定を追加
        paddle_coords = self.canvas.coords(self.paddle)
        if self.check_overlap(ball_coords, paddle_coords):
            self.dy = -self.dy  # ボールの方向を反転

        # ブロックとの衝突判定
        for block in self.blocks:
            if self.canvas.coords(block) and self.check_overlap(ball_coords, self.canvas.coords(block)):
                self.canvas.delete(block)  # ブロックを削除
                self.dy = -self.dy  # ボールの方向を反転

    def check_overlap(self, ball_coords, rect_coords):
        return not (ball_coords[2] < rect_coords[0] or ball_coords[0] > rect_coords[2] or
                    ball_coords[3] < rect_coords[1] or ball_coords[1] > rect_coords[3])

root = tk.Tk()
game = BlockBreaker(root)
root.mainloop()
ボールを動かしてブロックを壊すシンプルなゲーム
ボールを動かしてブロックを壊すシンプルなゲーム

グラフやチャートの描画

Canvasを使用して、データを視覚化するためのグラフやチャートを描画することもできます。

以下は、簡単な棒グラフを描画する例です。

import tkinter as tk
def draw_bar_chart(canvas, data):
    max_height = max(data)
    for i, value in enumerate(data):
        x1 = i * 50 + 10
        y1 = 200 - (value / max_height * 200)
        x2 = x1 + 40
        y2 = 200
        canvas.create_rectangle(x1, y1, x2, y2, fill="blue")
        canvas.create_text(x1 + 20, y1 - 10, text=str(value))
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
data = [50, 80, 30, 100, 60]  # データ
draw_bar_chart(canvas, data)
root.mainloop()
指定したデータに基づいた棒グラフが描画される

インタラクティブなGUIの作成

Canvasを使って、インタラクティブなGUIを作成することも可能です。

以下は、ユーザーが図形を描画できる簡単なアプリケーションの例です。

import tkinter as tk
def draw_shape(event):
    x, y = event.x, event.y
    canvas.create_oval(x-10, y-10, x+10, y+10, fill="purple")
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=300)
canvas.pack()
canvas.bind("<Button-1>", draw_shape)  # クリックで図形を描画
root.mainloop()
クリックした位置に紫色の円が描画される

画像編集ツールの作成

Canvasを使用して、簡単な画像編集ツールを作成することもできます。

以下は、画像を読み込んで、クリックした位置に円を描画する例です。

import tkinter as tk
from PIL import Image, ImageTk
def load_image(canvas):
    image = Image.open("example.png")
    photo = ImageTk.PhotoImage(image)
    canvas.create_image(0, 0, image=photo, anchor="nw")
    canvas.image = photo
def draw_circle(event):
    x, y = event.x, event.y
    canvas.create_oval(x-10, y-10, x+10, y+10, outline="red")
root = tk.Tk()
canvas = tk.Canvas(root, width=400, height=300)
canvas.pack()
load_image(canvas)  # 画像を読み込む
canvas.bind("<Button-1>", draw_circle)  # クリックで円を描画
root.mainloop()
画像上にクリックした位置に赤い円が描画される

このように、TkinterのCanvasは多様なアプリケーションに応用でき、ゲームやデータの視覚化、インタラクティブなGUI、画像編集ツールなど、さまざまな機能を実現することができます。

Canvasを活用することで、より魅力的でインタラクティブなアプリケーションを作成することが可能です。

まとめ

この記事では、PythonのTkinterライブラリを使用したCanvasの基本的な使い方から、図形や画像の描画、イベント処理、座標系の理解、さらには応用例に至るまで幅広く解説しました。

Canvasは、インタラクティブなアプリケーションやゲーム、データの視覚化など、さまざまな用途に活用できる強力なツールです。

これを機に、実際にCanvasを使ったプロジェクトに挑戦し、より多くの機能を試してみることをお勧めします。

関連記事

Back to top button