どん底から這い上がるまでの記録

どん底から這い上がりたいけど這い上がれない人がいろいろ書くブログ(主にプログラミング)

Canvasを使ってみる。

今回はCanvasを使っていろいろやってみます。

今回やることは

  ・Canvasを貼る。

  ・線を引く。

  ・長方形を描いてみる。

  ・文字を描く。

  ・画像を貼り付ける。

Canvasを貼る。

はじめに、メインウィンドウを作成します。x=300, y=100の位置にウィンドウが出るように設定した。

import tkinter as tk
root = tk.Tk() # メインウィンドウ
root.geometry("+{}+{}".format(300,100))

次に、Canvasのオブジェクトを作成します。オブジェクトの作り方は

widget = Canvas(parent, option...) のような感じです。

canvas = tk.Canvas(root, bg='green', width=300, height=300)

parentはCanvasの配置先を指定します。メインウィンドウに配置するので、rootとしています。

次に、作成したCanvasをメインウィンドウに貼り付けます。メインウィンドウのx=0, y=0の位置に配置しました。

canvas.place(x=0, y=0)
root.mainloop() # アプリケーションの開始

これでCanvasをメインウィンドウに貼るプログラムの完成です。

コード全体は下のようになります。これを実行すると、下のようなウィンドウが立ち上がるはずです。

import tkinter as tk
root = tk.Tk() # メインウィンドウ
root.geometry("+{}+{}".format(300,100))
canvas = tk.Canvas(root, bg='green', width=300, height=300)
canvas.place(x=0, y=0)
root.mainloop() # アプリケーションの開始

 

f:id:pytry3g:20180208164418p:plain

 

線を引く。

Canvasに線を引いてみます。線を引くにはcreate_lineメソッドを使います。

create_line(coords, **options)

coordsには座標を指定します。

例えば、こんな感じ。

line1 = canvas.create_line(10, 10, 20, 20, fill='blue')

ここでやってることは、x,yの座標10のところからx,yの座標20に向かって線を引いています。optionのfillで線の色を青色にしています。

座標は4つ以上指定できます。例えば、

line2 = canvas.create_line(40, 40, 60, 60, 60, 40, fill='red')

ここでは、まずx,yの座標40からx,yの座標60に向かって線が引かれます。それからxが60、yが40のところに向かって線が引かれます。

言葉だけの説明では分かりにくいかもしれないので、画像を貼っときます。

f:id:pytry3g:20180208172349p:plain

長方形を描いてみる。

Canvasには円や長方形などの図形を描くことができます。

ここでは長方形を描いてみたいと思います。長方形を描くにはcreate_rectangleメソッドを使います。

create_rectangle(bbox, **options)

bboxには長方形の左上の頂点の座標と右下の頂点の座標が入ります。

f:id:pytry3g:20180208165325p:plain

コード例

# create_rectangle(x0, y0, x1, y1, **options)
rect = canvas.create_rectangle(100, 100, 120, 120, fill='skyblue', outline="green")

fillは図形の色。outlineは図形の辺の色。

文字を描く

Canvas上に文字を描いてみます。

文字を描くにはcreate_textメソッドを使います。

create_text(position, **options)

positionには座標を指定します。指定した座標にテキストの中心がきます。

canvas.create_text(10, 80, text="王", fill='red', font=('Arial', 10, 'bold'))

上の例では、文字の中心座標がx=10, y=80のところに来るようになっています。

optionsでいろいろ設定をしています。

画像を貼り付ける

最後に画像をCanvasに貼ってみます。

画像を貼り付けるには画像ライブラリのPillowを使います。Pillowを使うとだいだいの画像は貼り付けることができます。

from PIL import Image, ImageTk

画像を読み込みます。

img = Image.open('sample.ico')
tkimg = ImageTk.PhotoImage(img)

create_imageメソッドでCanvasに貼り付けます。

create_image(position, **options)

canvas.create_image(150, 150, image=tkimg)

 これで、キャンバス上に画像が貼り付けられているはずです。

※注意※

下のプログラムはキャンバス上に画像を貼り付けるプログラムです。実行してみるとわかりますが、画像の貼り付けに失敗します。画像は表示されません。

理由はここのページのcreate_imageのところに説明がありました。

The application must keep a reference to the image object.

どうやらアプリケーションは画像オブジェクトを保持し続けなければならないようです。

import tkinter as tk
from PIL import Image, ImageTk


class App(tk.Tk):
    def __init__(self):
        super(App, self).__init__()
        self.title('Event sample')
        self.geometry("{}x{}+{}+{}".format(300, 300, 300, 100))
        self.iconbitmap('python.ico')

        self._set_widget()
        self._put_widget()

    def _set_widget(self):
        ### Canvas ###
        self._canvas = tk.Canvas(self, bg='white', width=300, height=300)

        # Rectangle
        self._canvas.create_rectangle(30, 30, 60, 60, fill="skyblue", outline="red")

        # Image
        img = Image.open("python.png").resize((100, 100), Image.ANTIALIAS)
        width, height = img.size
        new_img = Image.new("RGBA", (width, height), (255, 255, 255))
        new_img.paste(img, (0, 0))
        tkimg = ImageTk.PhotoImage(new_img)
        self._canvas.create_image(190, 190, image=tkimg)

    def _put_widget(self):
        self._canvas.place(x=0, y=0)

    def run(self):
        self.mainloop()


if __name__ == "__main__":
    app = App()
    app.run()

 

 上のコードの_set_widgetメソッドの以下の部分を直さなければなりません。

        tkimg = ImageTk.PhotoImage(new_img)
        self._canvas.create_image(190, 190, image=tkimg)

コードを以下のように変えてみます。作成した画像オブジェクトをインスタンス変数に入れることにより、アプリケーションは画像オブジェクトを保持し続けることができます。

    def _set_widget(self):
        ### Canvas ###
        self._canvas = tk.Canvas(self, bg='white', width=300, height=300)

        # Rectangle
        self._canvas.create_rectangle(30, 30, 60, 60, fill="skyblue", outline="red")

        # Image
        img = Image.open("python.png").resize((100, 100), Image.ANTIALIAS)
        width, height = img.size
        new_img = Image.new("RGBA", (width, height), (255, 255, 255))
        new_img.paste(img, (0, 0))
        self._image = ImageTk.PhotoImage(new_img)
        self._canvas.create_image(190, 190, image=self._image)