after()でリアルタイム処理を行う
Pythonのリアルタイム処理はafter()を使う。下記コードはウィンドウのラベルに秒数が刻々と表示される。
import tkinter as tk
tmr = 0 # 経過時間を記録する変数
def counter():
global tmr # 関数内の変数tmrをグローバル変数のtmrとして扱う宣言
tmr = tmr + 1
label["text"] = tmr
root.after(1000, counter) # 1秒毎にcounter()を実行
root = tk.Tk()
root.title("リアルタイム処理で秒数をカウント")
root.geometry("400x300")
label = tk.Label(font=("Ubunt Mono", 160))
label.pack()
counter() # 最初のcounter()を実行しリアルタイム処理を始める
root.mainloop()
15行目でリアルタイム処理を実行するループ用関数counter()を呼び出す。counter()内でafter()を呼び出している。第一引数に待機時間、第二引数に実行する処理。待機時間はミリセコンド秒(1秒の1000分の1)で指定。上記コードでは1000ミリセコンド、つまり1秒後にcounter()即ち自分自身を呼び出す。
[書式]
after(ミリセコンド秒, 実行する関数名)
プログラムが終了するまで延々秒数をカウントし続ける。
キー入力
Pythonでイベントを受け取るにはbind()を使う。下記コードはキーイベントを取得し、ラベルにキーに割り当てられた値を表示している。
import tkinter as tk
key = 0
def key_down(e):
global key
key = e.keycode # 引数eはイベント情報が格納されており、keycodeから押されたキー情報を取得、代入
label["text"] = "押したキー:" + str(key) # ラベルに押されたキーの値を書き込む
root = tk.Tk()
root.title("tkinterで入力を取得")
root.geometry("400x300")
label = tk.Label(font=("Ubunt Mono", 24))
label.pack()
root.bind("<KeyPress>", key_down) # 第一引数に<KeyPress>を指定し、キーが押下時のハンドラを登録
root.mainloop()
15行目でbind()でイベントを設定している。第一引数にイベントの種類、第二引数にイベントハンドラを登録。
関数key_down()の引数eはイベント情報が格納されている。名前は必ずしもeである必要はないが、大抵はeまたはevent。変数eから.keycodeでキー情報を取得可能。
[書式]
bind("<イベント>", イベント発生時に実行する関数)
代表的なイベント | 内容 |
---|---|
<KeyPress>あるいは<Key> | キーダウン |
<KeyRelease> | キーアップ |
<Motion> | マウスポインターの移動 |
<ButtonPress>あるいは<Button> | マウスボタンのクリック |
<Button-1> | マウスの左ボタンのクリック |
<Button-2> | マウスの中央ボタンのクリック |
<Button-3> | マウスの右ボタンのクリック |
実行しキーを押した結果。
キャラクターをキー入力で動かしてみる
クライアント領域に画像を表示し、方向キーで上下左右に動かす。
import tkinter as tk
key = ""
def key_down(e):
global key
key = e.keysym # 引数eはイベント情報が格納されており、keysymから押されたキー情報を取得、代入
def key_up(e): # キーが離された時点でキー情報をリセットする
global key
key = ""
cx = 200 # 自機のX座標
cy = 200 # 自機のY座標
def main_proc(): # リアルタイム処理を実行する関数
global cx, cy
if key == "Left":
cx = cx - 20
if key == "Right":
cx = cx + 20
if key == "Up":
cy = cy -20
if key == "Down":
cy = cy + 20
canvas.coords("MYCHR", cx, cy) # 自機画像の描画位置を移動
root.after(100, main_proc) # 100ミリセコンド後、もう一時自分自身を呼び出す
root = tk.Tk()
root.title("tkinterでキャラクター移動")
root.bind("<KeyPress>", key_down)
root.bind("<KeyRelease>", key_up)
canvas = tk.Canvas(width=800, height=600)
canvas.pack()
img = tk.PhotoImage(file="drone_car.png") # 自機画像の読み込み
canvas.create_image(cx, cy, image=img, tag="MYCHR") # キャンバスに画像を描画
main_proc()
root.mainloop()
14行目のリアルタイム処理用関数main_proc()では、押された方向キーに応じてXもしくはY座標を20ピクセル増減。
画像を描画している34行目、それに対応する24行目で”MYCHR”というタグを指定。タグとはキャンバスに描画する図形や画像に指定でき、そのオブジェクトを示す一意の名前。タグは自由に名付け可能。
マウスイベントを受け取る
ウィンドウ上(クライアント領域)でマウス操作時のイベントを受け取る。下記コードはマウスの動き、ボタンクリックの有無を動的に判定する。
import tkinter as tk
mouse_x = 0
mouse_y = 0
mouse_c = "Off"
def mouse_move(e): # マウスが動いた時に実行
global mouse_x, mouse_y
mouse_x = e.x # 現在のマウスカーソルのX、Y座標に代入
mouse_y = e.y
def mouse_press(e): # マウスボタンがクリックされた時に実行
global mouse_c
mouse_c = "On"
def mouse_release(e): # マウスボタンが離された時に実行
global mouse_c
mouse_c = "Off"
def mouse_proc(): # リアルタイム処理関数
fnt = ("Ubuntu Mono", 20) # フォント情報を定義
txt = "X座標{}, Y座標{}, クリック状態{}".format(mouse_x, mouse_y, mouse_c) # 表示する文字列を整形し代入
canvas.delete("INFOTEXT") # 繰り返し処理の最初に文字列をクリア
canvas.create_text(300, 30, text=txt, fill="black", font=fnt, tag="INFOTEXT") # キャンバスに文字列を描画
root.after(100, mouse_proc)
root = tk.Tk()
root.title("tkinterでマウス入力を受け取る")
root.resizable(False, False)
root.bind("<Motion>", mouse_move) # マウスがクライアント領域上で動いた時に呼ぶ関数を指定
root.bind("<ButtonPress>", mouse_press) # マウスボタンがクリックされた時に呼ぶ関数を指定
root.bind("<ButtonRelease>", mouse_release) # 押されていたマウスボタンが離された時に呼ぶ関数を指定
canvas = tk.Canvas(root, width=600, height=400)
canvas.pack()
mouse_proc()
root.mainloop()
現在のマウスカーソルのX、Y座標をリアルタイムで表示・更新し続ける。ボタンクリック時はOn、離されるとOffと表示。画像にカーソルが映っていないがウィンドウ右下辺りに存在。
22行目の表示する文字列の整形では、左の{}に右のformat()の引数が並び順で置き換えられる。
[書式]
"{}, {}, ...".format(中身を表示したい変数, "指定したい文字列", ...)
コメント