kuroの覚え書き

96の個人的覚え書き

PythonでGUIアプリを作る

プログラミングの練習も兼ねてPythonでゲームを作ってみる。
まずはtkinterの使い方練習。

import tkinter    #tkinterモジュールをインポート

root = tkinter.Tk()    # ウィンドウの部品を作る
root.geometry("400x300")      #ウィンドウのサイズを決める
root.title("PythonでGUIを扱う")   #ウィンドウのタイトルを指定
label = tkinter.Label(text="GUIのウィンドウを開く", font=("Times New Roman", 20))      #ラベルの部品を作る
label.place(x=80,y=60)    #ラベルを配置
button = tkinter.Button(text="button", command=button_click)      #ボタンを作る
button.place(x=80,y=100)        #ボタンを配置
text = tkinter.Entry(width=20)      #テキストの入力欄を作る
text.place(x=80,y=140)      #入力欄を配置

root.mainloop()   #ウィンドウを表示

f:id:k-kuro:20200503200139p:plain
tkinter

背景の挿入を試す。

import tkinter    #tkinterモジュールをインポート
from PIL import ImageTk

root = tkinter.Tk()    # ウィンドウの部品を作る
root.title("Canvasに画像を描画する")   #ウィンドウのタイトルを指定
canvas = tkinter.Canvas(width=480, height=300)      #ウィンドウのサイズを設定
canvas.pack()       #canvasを作成
img_bg = ImageTk.PhotoImage(file="id_1.png")        #イメージを読み込み
canvas.create_image(240, 150, image=img_bg)     #イメージの中心を設定

root.mainloop()   #ウィンドウを表示

最初、書籍通りにやってみると

Traceback (most recent call last):
  File "canvas_test.py", line 8, in <module>
    img_bg = tkinter.PhotoImage(file="id_1.png")
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 3545, in __init__
    Image.__init__(self, 'photo', name, cnf, master, **kw)
  File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 3501, in __init__
    self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't recognize data in image file "id_1.png"

こういうエラーが出た。
どうやらpython3の標準ライブラリのtkinterモジュールではpngが扱えないことが原因らしい。

img_bg = tkinter.PhotoImage(file="id_1.png")        #イメージを読み込み

こうなっていたからだめだった模様。
Pillowモジュールをインストールして

from PIL import ImageTk

とした上で

img_bg = ImageTk.PhotoImage(file="id_1.png") 

これでちゃんと表示されるようになった。

f:id:k-kuro:20200506003720p:plain
canvas


マウスの位置検知とヒットチェック(オブジェクトが重なっているかどうか判定)

import tkinter
from math import sqrt        #平方根の計算のため

def hitcheck_circle():
    dist = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
    if dist <= r1 + r2:    #中心間の距離が半径の和より短いか
        return True
    return False

def mouse_move(e):
    global x1, y1  #マウスの指す位置
    x1 = e.x
    y1 = e.y
    col = "green"
    if hitcheck_circle()== True:
        col = "yellow"
    canvas.delete("CIRC1")
    canvas.create_oval(x1-r1,y1-r1,x1+r1,y1+r1, fill=col, tag="CIRC1")

root = tkinter.Tk()
root.title("円によるヒットチェック")
canvas = tkinter.Canvas(width=400, height=400, bg="white")
canvas.pack()
canvas.bind("<Button>", mouse_move)     #マウスクリックしたところに円を置く

x1 = 50
y1 = 50
r1 = 40
canvas.create_oval(x1-r1,y1-r1,x1+r1,y1+r1, fill="green", tag="CIRC1")

x2 = 200
y2 = 200
r2 = 60
canvas.create_oval(x2-r2,y2-r2,x2+r2,y2+r2, fill="red")

root.mainloop()

f:id:k-kuro:20200506185939p:plain
hitcheck
だいぶゲームの基本ができてきたかも。


文字を入力してボタンを押した時に計算させる仕組み。これでこれまでWebアプリで作ってきたプログラムをそのままデスクトップアプリに作り変えることもできそうだ。

import tkinter    #tkinterモジュールをインポート
import math

def button_click():
    try:
        d = float(entry.get())
        a = math.radians(d)
        s = math.sin(a)
        c = math.cos(a)
        t = math.tan(a)
        label_s["text"] = "sin "+str(s)
        label_c["text"] = "cos "+str(c)
        label_t["text"] = "tan "+str(t)
        label_e["text"] = ""
    except:
        label_s["text"] = "sin "
        label_c["text"] = "cos "
        label_t["text"] = "tan "
        label_e["text"] = "角度を入力してください"

root = tkinter.Tk()    # ウィンドウの部品を作る
root.geometry("400x300")      #ウィンドウのサイズを決める
root.title("三角関数計算機")   #ウィンドウのタイトルを指定
button = tkinter.Button(text="計算する", command=button_click)      #ボタンを作る
button.place(x=120,y=20)        #ボタンを配置
entry = tkinter.Entry(width=10)      #テキストの入力欄を作る
entry.place(x=20,y=20)      #入力欄を配置
label_s = tkinter.Label(text="sin ", font=("Times New Roman", 20))
label_s.place(x=20, y=80)
label_c = tkinter.Label(text="cos ", font=("Times New Roman", 20))
label_c.place(x=20, y=120)
label_t = tkinter.Label(text="tan ", font=("Times New Roman", 20))
label_t.place(x=20, y=160)
label_e = tkinter.Label(text="角度を入力してください", font=("Times New Roman", 10))
label_e.place(x=20, y=60)
root.mainloop()   #ウィンドウを表示

f:id:k-kuro:20200506194214p:plain
起動時
f:id:k-kuro:20200506194239p:plain
計算させると