tkinter でウィジェットを自動的に大量配置する方法
Posted on 2024年03月23日 (土) in 雑記
目次
thinter でウィジェットを配置する方法
tkinter では「ウィジェットで使う変数や関数の定義 → ウィジェットの定義 → ウィジェットの配置」という順番でコードを書いていきます。
例としてこのような形です。
import tkinter as tk
# ソフトのウィンドウを作成
root=tk.Tk()
# ボタンクリック時の関数定義
def button_click():
print("aaa")
# ボタンの定義
button=tk.Button(root,text="aaaを表示",command=button_click)
# ボタンを実際に配置
button.place()
# ソフトの維持
root.mainloop()
しかしソフト製作時など、ボタンを大量に定義・配置するのが面倒くさいと感じる人がいるかも知れません。
一応ネットで調べると、「functools ライブラリの partial」を使う方法が出てきますが、この方法ではボタンの大量定義と配置はできてもボタンの変数を区別できないため、後から呼び出すことができません。
そこで今回はボタンの変数を個別に分けて定義しつつ、大量に配置していく方法を紹介していきます。
今回紹介するやり方の考え方
今回紹介する方法では、「ループごとに個別の変数を定義し、各ボタンを振り分ける」ということを行っていきます。
しかし、個別にボタンの変数を定義するためには「ループごとに異なる変数の定義・ボタンに対応した関数の呼び出し」が必要であり、このやり方はあまり有名ではないです。
ここでは「ループごとに異なる文字列を生成 → 文字列を変数や関数名に変換する」を行うことで、個別のボタン変数を定義・配置していきます。
文字列を変数・関数名に変更するコード
Python ではこのように簡単に文字列を変数名に変換する事ができます。
# グローバル関数の定義
global_variable="グローバル変数ですよ"
# 文字列を使って変数名を呼び出し
print(globals()["global_variable"])
# 出力結果
>> グローバル変数ですよ
# ローカル変数を呼び出す場所の作成
def function_example():
# ローカル関数の定義
local_variable="ローカル変数ですよ"
# 文字列を使って変数名を呼び出し
print(locals()["local_variable"])
# 関数呼び出し
function_example()
# 出力結果
>> ローカル変数ですよ
この例は変数名をテキストから変換していますが、関数も全く同じやり方で呼び出すことができます。
なお上記の通りグローバル変数とローカル変数では呼び出し方が異なるので注意してください。
globals()[]
やlocals()[]
の中身は文字列ならばよいため、ループごとに異なる文字列を作るようにすれば異なる変数・関数を作ることができます。
実際にボタンを設置した例がこちらです。
import tkinter as tk
# ソフトのウィンドウを作成
root=tk.Tk()
# ボタンクリック時の関数定義
def button_click1():
print("aaa")
def button_click2():
print("bbb")
def button_click3():
print("ccc")
# ボタンの定義と配置を自動化
for i in range(3):
globals()[f"button{i+1}"]=tk.Button(root,text="表示",command=globals()[f"button_click{i+1}"])
globals()[f"button{i+1}"].grid(row=0,column=i)
# ソフトの維持
root.mainloop()
このようにコードを書くことで、ボタンの定義とボタンの配置を自動化できます。
このやり方だと変数名や関数名が制限されてしまいますが、リストを活用するなどで対策は可能です。
このやり方は tkinter 以外のライブラリでも使えますし、覚えておくと便利なやり方ですので、ぜひ覚えていってください。
終わりに
このやり方は、Yukis Army knife という自作ソフトでボタンを大量配置するのがめんどくさくなったため考えました。
Yukis Army knife では実際もっと複雑なやり方でボタンの振り分け・配置をしていますが、基本今回紹介したやり方です。
変数名や関数名を文字列から変換するコードは他にもあるようですが、多分このやり方が一番分かりやすいと思います。
なおソフト外部からの操作が介在する場所に、このやり方は使わないでください。
例えばテキスト入力欄の内容をこの globals 関数などに入れてしまうと、任意のコードが実行可能になり良くない結果となるため、基本的に定数の時のみこの関数を使ってください。