LoginSignup
2
2

More than 3 years have passed since last update.

【Python】for文で生成されたボタンの引数を変更したい!

Last updated at Posted at 2019-09-02

きっかけ

pythonのTkinterを使ってUIを作っていた時に困ったのでココに覚書と同じ初心者を救いたい

楽したいのでpython使った
楽したいのでclassとfor文使ってButtonを複数生成した
そしたらハマった
楽したいのにー!

押しても同じ反応しかしないButton達

classの勉強も兼ねて無理やりclassでButton達を作ってみました
が…
同名の変数の内容がボタンの引数に反映されてないっぽいぞ?
for文で生成してもダメでした
その時のコードがこちら

code.py
# GUI作成用
import tkinter as tk

# 色付きボタンの素になるタプル達
BCG = [
    #('色名', '背景', '文字', '配置')
    ('赤', 'red', 'white', 'left'),
    ('緑', 'green', 'white', 'left'),
    ('青', 'blue' , 'white', 'left'),
    ('橙', 'orange' , 'black', 'left'),
    ('茶', 'brown' , 'white', 'left'),
    ('桃', 'pink' , 'black', 'left'),
    ('無', None, None, 'right')
]

# 何かしらの条件で変数judgement_boolを書き換える関数
def judgement_bool_changer():
    global judgement_bool
    if(len(text_temp) == 0 or len(title_temp) == 0):
        judgement_bool.set(False)
    else:
        judgement_bool.set(True)

# ボタンを押した時に呼ばれる関数
def text_background_color(bg, fg, judgement_bool):
    # 何かのおまじない
    # 関数内で関数使うといいよと書かれてたので使用
    # これに関しては紹介ページが多いので割愛
    def x():
        # 第三引数がTrueだとbgとfgをヌリヌリする
        # 内容は省略
    return x

# ボタン達を生成するクラス
class BCG_Frame(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.pack(fill = 'x', side = 'top')
        self.createWidgets(BCG)

    def createWidgets(self, bcg):
        for face, bgc, fgc, side in bcg:
            # Buttonを複数生成するfor文内にやりたいことを素直に記述
            tkbutton = tk.Button(text = face, bg = bgc, fg = fgc, command = text_background_color(bgc, fgc, judgement_bool.get()))
            tkbutton.pack(side = side)

def main():
    root = tk.Tk()
    # ウィンドウを最前面に持ってくる
    root.attributes('-topmost', True)
    root.title('test')

    # 初期設定
    judgement_bool = tk.BooleanVar()
    judgement_bool.set(False)

    # カラフルボタン群生成
    button_bcg = BCG_Frame(master=root)
    button_bcg.pack()

    root.mainloop()

if __name__ == '__main__':
    main()

現状のMacではちゃんと表示されないのでスクリーンショットは割愛

classを使用して満足感に浸っていると
あれ?
何をしてもButton達がFalseひっさげてお仕事してくれない

成功例

24時間以上検索してもこの問題に立ち向かえる検索結果に出会えない(日本語)
と諦め掛けていたその時ちらっと見えたとあるサイトを参考にして書いたコードが下記になります

コード

変更・追記箇所のみ表記

code.py
# ボタンを押した時に重い腰を上げる関数を追記 超重要
def make_command(paint_array):
    return lambda:text_background_color(paint_array, judgement_bool.get())()

# ボタン達を生成するクラス
class BCG_Frame(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master)
        self.pack()
        self.createWidgets(BCG)

    def createWidgets(self, bcg):
        for face, bgc, fgc, sides in bcg:
            # ボタンを押した時に上記の関数を呼び出す様に変更
            tkbutton = tk.Button(text = face, bg = bgc, fg = fgc, command = make_command([bgc, fgc]))
            tkbutton.pack(side = sides)

たったの二行追記し少し変更しただけなのに…

最後に

for文で生成したButtonは生成時の引数を固定して維持してしまうコトがわかりました
そこでButtonを押した時に重い腰をあげる関数にButtonが押されたよと呼び出すコトで引数をリアルタイムで反映させるコトができました

チェックボックスの検索結果ばかり出てきてイライラしてたら出てきたページがこちら
M.Hiroi's Home Page / Lightweight Language
これで各Button達が実力を発揮してくれる様になりました
上記ページの作成者様感謝します

チェックボックスが嫌いになりかけました
フゥ

追記というか何か

おまじないの「関数内で関数」を使っているので呼び出した関数に括弧がもう1セット必要になりますご注意あれ
text_background_color(paint_array, judgement_bool.get())()

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2