tkinterで【脳トレ】GUIを作ってみました


# 作ったもの
【脳トレ：東京23区ぜんぶ言えますか？】
その名の通り、東京23区をひとつづつ答えていき全問正解を目指すアプリです。
意外と出てこなくて、頭の体操になります。


# 作ろうと思ったきっかけ
母が脳トレとして東京23区を書き出すということをしていて、
私や息子がやってみてもなかなか難しかったのでアプリにしてみようと思いました。


# 実装したいこと
* 正解　or　不正解を表示する。
* あと何区残っているのか表示する。
* 解答したものが正解だった場合に、答えたものを表示していく。
* 「ギブアップする」で残りの答えを表示する。
* 「はじめからやりなおす」でリセットする。
* いらすとやさんの画像を使って見た目を可愛くする。



# コード
```python
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from PIL import Image, ImageTk
import pandas as pd

#csvファイルで正解のリストを用意する
df = pd.read_csv("23ku.csv",index_col=0)
kumei = df["区名"].to_list()

#解答の入れ物
kotae = []

root = tk.Tk()
root.title("東京23区")
root.geometry("900x800")
fonts =("",20)

lblt = tk.Label(text="「 ◯◯区 」と入力  →  enterキー を押してください",font=("",30,"bold"))
lblt.pack(pady=30)


#確認ボタン：入力した値を取得してリストにあるか検索し、結果をラベルへ表示する
def btn_click1(self):
    word = entry.get()
    entry.delete(0,tk.END)
    
    #すでに解答済みだった場合のメッセージ
    if word in kotae:
        lbl2.configure(text = "もう出てるよー",font=fonts)
        entry.focus_set()
        
    #正解の時のメッセージ
    elif word in kumei:
        lbl2.configure(text = "正解！",font=fonts)
        entry.focus_set()

        #正解だったら解答をリストに入れて表示
        kotae.append(word)
        lbl1.configure(text = '\n'.join(kotae),font=fonts)

        #全問正解した時のメッセージ
        if len(kotae)== 23:
            lbl3.configure(text = "全問正解！すばらしい！",font=fonts)
            
        #残り数のメッセージ
        else:
            lbl3.configure(text = "あと" + str(23-len(kotae)) + "区がんばれー",font=fonts)

    #不正解の時のメッセージ
    else:
        lbl2.configure(text = "ないよー",font=fonts)
        entry.focus_set()


#ギブアップボタン：正解と答えを比較して残りを表示
def btn_click2():
    res = tk.messagebox.askyesno("確認", "本当に見る?")
    
    if res == True:
        nokori = set(kumei) ^ set(kotae)
        lbl4.configure(text = '\n'.join(nokori),font=fonts)
        lbl2.configure(text = "お疲れさまでしたー",font=fonts)
        lbl3.configure(text = "↓答えられなかったところ",font=fonts)
    
 
#はじめからやりなおすボタン
def btn_click3():
    res = tk.messagebox.askyesno("確認", "全部消していい?")

    if res == True:
        entry.delete(0,tk.END)
        kotae.clear()
        lbl1.configure(text="")
        lbl2.configure(text="")
        lbl3.configure(text="")
        lbl4.configure(text="")
        entry.focus_set()


#解答box
entry = tk.Entry(root, font=("",30))
entry.focus_set()
entry.place(x=80, y=100, width=200, height=50)
entry.bind('<Return>',btn_click1)


btn2 = ttk.Button(root,text='ギブアップ( 残りを見る )',command=btn_click2)
btn2.place(x=600,y=100,width=170)

btn3 = ttk.Button(root,text='はじめからやりなおす',command=btn_click3)
btn3.place(x=600,y=150,width=170)


#ラベル1
lbl1 = tk.Label(text = "")
lbl1.place(x=80,y=180)
#ラベル2
lbl2 = tk.Label(text = "")
lbl2.place(x=350,y=100)
#ラベル3
lbl3 = tk.Label(text = "")
lbl3.place(x=350,y=130)
#ラベル4
lbl4 = tk.Label(text = "")
lbl4.place(x=350,y=180)


#画像1
img1 = Image.open('rainbow_bridge.png')
img1 = img1.resize((200,150))
img1 = ImageTk.PhotoImage(img1)

canvas = tk.Canvas("", width=200, height=150,highlightthickness=0)
canvas.place(x=550, y=250)
canvas.create_image(0,0, image=img1,anchor="nw")


#画像2
img2 = Image.open('tokyo_skytree.png')
img2 = img2.resize((120,180))
img2 = ImageTk.PhotoImage(img2)

canvas = tk.Canvas("", width=120, height=180,highlightthickness=0)
canvas.place(x=750, y=200)
canvas.create_image(0,0, image=img2,anchor="nw")


#画像3
img3 = Image.open('hirameki_woman.png')
img3 = img3.resize((280,320))
img3 = ImageTk.PhotoImage(img3)

canvas = tk.Canvas("", width=280, height=320,highlightthickness=0)
canvas.place(x=550, y=400)
canvas.create_image(0,0, image=img3,anchor="nw")


tk.mainloop()

```



# 工夫したこと
* enterを押すことで答え合わせができるので、スピーディに解答できるようにしました。
* 「ギブアップ」と「はじめからやりなおす」ボタンではメッセージボックスを表示するようにしました。


# 実行例
![23ku.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2967238/d0c344a8-ae44-7e19-1a73-715b93f8a82a.gif)




# 出来上がりの感想
予測変換がヒントになってしまうのが気になるところです。(一応プライベートモードを使用)
今回は東京23区ですが、csvファイルと内容を少しいじったら47都道府県もいけるかなと思います。
調べながら少しずつ改善して作ったものなので、とても楽しく勉強になりました。
コードの順番やもっと短縮できるものがあるかと思います、アドバイスやご指摘をいただけると嬉しいです。