クリックした場所に円を出すよ!イベントと関数の使い方をおぼえよう

クリックした場所に円を出すよ!イベントと関数の使い方をおぼえよう

クリックで動かす仕組みを作ろう!

前回の記事で円を描く方法を覚えたら、次は「クリックした場所に円を描く」というのをやってみるよ。前にもクリックできるボタンを作ったことがあるけど、そのときにもでてきた「イベント」の考え方が大事なんだ。書き方はちょっと違うからそのあたりも見ていくよ。

クリックと関数を結びつけよう!

前にボタンとクリックイベントを結びつけたときは「command=関数名」って書きかたをしたよね。

button_01 = tk.Button(root, text="チェック", font=("Helvetica",20), command=ButtonClick)

でもキャンバスの場合は「bind()」を使うんだ。書きかたはこんな感じ。

canvas.bind(①イベント名, ②関数名)

①イベント名のところには「マウスクリック」や「キーを押したら」みたいな動作が入る。②はそのときに実行したい関数名が入るんだね。①のイベント名は下のような書きかたがあるから注意だ。

<キーの装飾 - イベント - 種類>

「キーの装飾」というのはShiftやCtrlなどの一緒に押されたキーの状態のこと。ここは必要なければ指定しなくてもいいんだけど、指定すると「Shiftを押しながらクリック」みたいな動作もできるようになるんだ。

イベントは「クリック」や「キーを押す」ってことだね。種類はイベントの種類。例えばクリックだったら「左クリックは1」みたいに決まってて、それを指定できるんだ。

それをまとめて書くとこんなふうになる。

canvas.bind("<Button-1>", click)

これでマウスの左ボタンで関数click()が実行されるようになる。「Button」がクリック、「1」が左ボタン、clickが実行する関数名って感じだね。

ちなみにマウスクリック以外のイベントもいろいろあるので、一覧でまとめてみたよ。

イベント 意味
Button / ButtonPress マウスが押された。種類は「1=左クリック」「2=右クリック」「3=中央ボタン」
ButtonRelease ボタンが放された。種類の指定はButtonと同じ
Key / KeyPress キーボードのキーが押された。種類はキーの番号
KeyRelease キーボードのキーが放された。種類はキーの番号
Enter 領域内にマウスポインタが入ってきた。
Leave 領域内からマウスポインタが出ていった。
Motion 領域内でマウスポインタ動いた。

イベントに情報を渡そう!

クリックなどのイベントと関数を結びつけるときに、とっても重要なことがある。それは「イベントの情報を関数に伝える」ことができるってことなんだ。例えば、マウスクリックのイベントなら、クリックした座標を取得するなんてことができるんだ。使い方はこんな感じ。

def click(event):
    #クリックされたときの処理

clickという関数を自分で定義してるんだね。そして変数にeventを設定してるんだ。こうしておくとeventにマウスの情報を伝えることが出来る。例えばクリックした座標を取得するならこんな書きかたでできるよ。

event.x : クリックした場所のX座標
event.y : クリックした場所のY座標

クリックした場所に円を出そう!

それじゃあ、ここまでの内容をまとめて「クリックした場所に円を描く」っていうプログラムを書いてみよう!こんな感じになるよ。

# codeing=utf-8
import tkinter as tk

def click(event):
    # クリックされた場所に描画する
    canvas.create_oval(event.x-20, event.y-20, event.x+20, event.y+20, fill="red", width=0)

#ウィンドウを作る
root = tk.Tk()
root.geometry("600x400")

#Canvasを作る
canvas = tk.Canvas(root, width=600, height=400, bg="white")
canvas.place(x=0, y=0)

#イベントを設定する
canvas.bind("<Button-1>", click)


root.mainloop()

▽ 実行結果(クリックした場所に円が出る)

ポイントは6行目の部分。「event.x-20」みたいに、マウスの座標を取得して円を描くのに使ってるんだね。

def click(event):
    # クリックされた場所に描画する
    canvas.create_oval(event.x-20, event.y-20, event.x+20, event.y+20, fill="red", width=0)

円を増殖じゃなくて移動にしよう!

ここまでのプログラムは円がどんどん増殖して描画されるよね。これを場所だけ移動するプログラムに書き換えてみるよ。

作り方としては、①いまある円を消す→②新しい円を出すって感じにする。円を消す方法はいろいろあるんだけど、「同じ場所に白い円を出して隠す」というのが簡単だからやってみよう。白いキャンバスに白い円を出せば消えてように見えるってことだね。

それじゃあ先にプログラムを書いちゃうよ。コピペして実行して動きをみてみよう。

# codeing=utf-8
import tkinter as tk

#円の座標
x = 300
y = 200

def click(e):
    global x,y
    #前の円を隠す
    canvas.create_oval(x-30, y-30, x+30, y+30, fill="white", width=0)
    #クリックされた場所に描画する
    canvas.create_oval(e.x-20, e.y-20, e.x+20, e.y+20, fill="red", width=0)
    x = e.x
    y = e.y

#ウィンドウを作る
root = tk.Tk()
root.geometry("600x400")

#Canvasを作る
canvas = tk.Canvas(root, width=600, height=400, bg="white")
canvas.place(x=0, y=0)

#イベントを設定する
canvas.bind("<Button-1>", click)


root.mainloop()

解説

追加したのは4〜15行目。

#円の座標
x = 300
y = 200
 
def click(e):
    global x,y
    #前の円を隠す
    canvas.create_oval(x-30, y-30, x+30, y+30, fill="white", width=0)
    #クリックされた場所に描画する
    canvas.create_oval(e.x-20, e.y-20, e.x+20, e.y+20, fill="red", width=0)
    x = e.x
    y = e.y

最初に注目なのは4〜6行目。前と同じ場所に白い円を出して隠すには、前の円の場所を保存しておかないといけないね。そのために作ったのが、このxとyの変数だ。最初は「x=300, y=200」を入れてるけど、これは何でもいい。仮に入れてるだけだよ。

次は9行目に注目。さっきの変数xとyは関数の外に作ったから、そのままではクリックしたときの関数の中では使えないんだ。だから9行目でグローバル変数として宣言してるんだね。実際に隠してるのはこの部分。

canvas.create_oval(x-30, y-30, x+30, y+30, fill="white", width=0)

xとyは「前の円の座標」に使うんだから、そこに白い円を出してるよ。円のサイズは「x-30,y-30…」とひとまわり大きくしてる。

新しい円を出してるのは12行目から。

    #クリックされた場所に描画する
    canvas.create_oval(e.x-20, e.y-20, e.x+20, e.y+20, fill="red", width=0)
    x = e.x
    y = e.y

「e.x-20〜」でクリックした場所の座標に新しい円を出して。そして次の13,14行目に注目。このタイミングでクリックしたマウスの座標をグローバル変数x,yに代入してるんだ。これで「いま出した円の座標を保存する」ってことが出来るんだね。次から白い円を出すのはこの場所になるので、隠して消せるってことだ。

今日のまとめ

  • bind()でイベントと関数を使おう!
  • イベントから関数に値を渡そう!