t-hom’s diary

主にVBAネタを扱っているブログです。

PythonでGUI版 筋トレメトロノームを作成 その2

前回は筋トレ用メトロノームをGUI化した。
thom.hateblo.jp

なるべく紹介済の機能に絞って書いたのでコードがとても冗長だ。
前回GUIパーツをそれぞれ変数に入れて扱っていたため、今回はPythonのデータ型(リスト、タプル、ディクショナリ)を使ってもう少しスッキリさせてた。

Pythonの基礎でこれらのデータ型が出てくるので、「何に使うねんこれ」と思うかもしれないけど、そのイメージを掴んでもらうためにも良いと思う。

コード

import tkinter as tk
import winsound
from time import sleep

root_window = tk.Tk()
root_window.geometry("200x160")

def start_clicked():
    replay = int(items["Replay"][1].get())
    count = int(items["Count"][1].get())
    high_tone = int(items["High tone"][1].get())
    low_tone = int(items["Low tone"][1].get())
    duration = int(items["Duration"][1].get())
    for i in range(replay):
        for j in range(count):
            winsound.Beep(55*2**low_tone,duration)
            sleep(1)
        winsound.Beep(55*2**high_tone,duration*2)
        sleep(1)

item_names = ["Replay", "Count", "High tone", "Low tone", "Duration"]
initials = [5, 3, 5, 3, 200]

items = {}

for item_name in item_names:
    items[item_name] = (
            tk.Label(
                master=root_window,
                text=item_name),
            tk.Entry(
                master=root_window,
                width=10))

btn = tk.Button(
    master=root_window,
    text="Start",
    command=start_clicked
    )

for i in range(5):
    lbl, ent = items[item_names[i]]
    lbl.place(x=5,y=5+(25*i))
    ent.place(x=70,y=5+(25*i))
    ent.insert(tk.END,initials[i])

btn.place(x=70,y=130)

root_window.mainloop()

リストについて

リストはVBAでいうコレクションのようなものだが、Pythonの場合[]の中にカンマ区切りで書くことで初期値を設定できる。

VBAの場合

初期値を設定する方法が無いので以下のように一つずつ要素を追加する。

Dim item_names As Collection
Set item_names = New Collection
item_names.Add "Replay"
item_names.Add "Count"
item_names.Add "High tone"
item_names.Add "Low tone"
item_names.Add "Duration"

Pythonの場合

このように一つずつ追加しても良いが、

item_names = list()
item_names.append("Replay")
item_names.append("Count")
item_names.append("High tone")
item_names.append("Low tone")
item_names.append("Duration")

以下のように単に[]内にカンマ区切りで同じリストを作成できる。

item_names = ["Replay", "Count", "High tone", "Low tone", "Duration"]

また、空のリストを作りたければitem_names=list()とも書けるし、item_names=[]とも書ける。

アンパックについて

Pythonではリストの内容を個別の変数に入れたいとき、次のようにインデックス指定で入れることもできるが、

a = item_names[0]
b = item_names[1]
c = item_names[2]
d = item_names[3]
e = item_names[4]

アンパックという記述方法があり、次のように書くとリストのそれぞれの要素が変数に入る。

a, b, c, d, e = item_names

これ、とても楽。

ディクショナリについて

VBAのディクショナリと同じく、キーと値の対応付けデータである。
空のディクショナリを作っているのがこちら。

items = {}

文字列でキーを指定して値を入れることで追加・更新ができる。

items["キー"] = 値

タプルについて

基本的にリストみたいなもの。ただし追加や削除などの操作ができない。
リストが主に同種データを扱うのに対し、タプルは異なる型のデータを纏める用途でよく使われるらしい。
ということで、ラベルとテキストボックスを纏めてみた。

コード中に登場する以下のループ内では、item_namesリストから取り出したitem_nameをキーとしてディクショナリitemsに、ラベルとテキストボックスのタプルを格納している。

for item_name in item_names:
    items[item_name] = (
            tk.Label(
                master=root_window,
                text=item_name),
            tk.Entry(
                master=root_window,
                width=10))

そして配置する際は、ディクショナリitemsからitem_namesリストのi番目のキーでタプルを取り出し、lblとentにアンパックしている。

for i in range(5):
    lbl, ent = items[item_names[i]]
    lbl.place(x=5,y=5+(25*i))
    ent.place(x=70,y=5+(25*i))
    ent.insert(tk.END,initials[i])

一方でテキストボックス読み出しの際は、ラベルを取り出す必要はないのでアンパックではなく[1]を指定してゲット。
※タプルの[0]にラベル、[1]にテキストボックスが入っている。

def start_clicked():
    replay = int(items["Replay"][1].get())
    count = int(items["Count"][1].get())
    high_tone = int(items["High tone"][1].get())
    low_tone = int(items["Low tone"][1].get())
    duration = int(items["Duration"][1].get())

使用したデータの組み合わせ図

f:id:t-hom:20190929133438p:plain

おわりに

データ型を覚えるとコードの冗長性が無くなってコーディングが楽になる。
今回は前回の半分くらいのコード量になった。
また、変数名を大量に管理する必要がなくなり、変更にも強くなる。

今回の記事で、あまりついてこれなかった方も、基礎をしっかり学ぶとより短い労力でコードを書けるということは伝わったかと思う。

ということで、学習がんばりましょう。

やさしいPython (「やさしい」シリーズ)

やさしいPython (「やさしい」シリーズ)

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。