Python(tkinter004: 子の要素を個別で変更_winfo_id)

■フレームの上にのせた複数のラベル(フレームの子の要素)を個別で変更する。
前回、winfo_childrenで子の要素をすべて変更することはできたけど、個別に変更する方法がないか試してみる。
サンプルコードは新しく作った。(50行程度のコードなので下にのせる)

単純にフレームの上に8×8でラベルを作り、適度にレイアウトを調整し、その下にボタンを配置したもの。ボタンを押すと、ランダムでラベルの背景色を黒か白にする。afterのメソッドを使って、指定の時間間隔で黒か白にし続ける。

ラベルは下のコードの通り、for文を使って、フレーム上にのせていく。ここで、それぞれのラベルのidをwinfo_idで取得してリストにしておく。

        self.base_frame = ttk.Frame(self, pady=0, padx=0)
        self.base_frame.pack(side='top')

        for i in range(0, COLUMN):
            for j in range(0, ROW):
                self.widgt1 = ttk.Label(self.base_frame, anchor="center", text="", font="10", background="white",
                                        padx=10, pady=1)
                self.widgt1.grid(column=i, row=j, padx=1, pady=1)
                self.child_id.append(self.widgt1.winfo_id())

ボタンを押したときのコードは下のようなもの。
上で作ったidのリストをコピーして、ランダムで黒にするか決める。リストから外れたものは白にする。その後、winfo_childrenを使って、ウィジットを変更できる情報を取得し、それぞれのwinfo_idがリストに含まれるかどうかを判断することで、黒にするか白にするか決める。

        id_list = self.child_id.copy()
        for child in id_list:
            removeflag = random.randint(0, 1)
            if removeflag == 0:
                id_list.remove(child)

        for child in self.base_frame.winfo_children():
            if child.winfo_id() in id_list:
                child.configure(background="#000000")
            else:
                child.configure(background="#ffffff")

もう少し効率の良いやり方もありそうだけど、とりあえず各ウィジットのidを使ったサンプルを作成してみた。
全体のコードは下のもの。

import tkinter as ttk
import random

ROW = 8
COLUMN = 8


class Function(ttk.Tk):
    child_id = []

    def __init__(self):
        super().__init__()
        self.title('Rand')
        self.geometry(str(COLUMN * 30) + "x" + str(ROW * 30))
        self.resizable(0, 0)

        self.base_frame = ttk.Frame(self, pady=0, padx=0)
        self.base_frame.pack(side='top')

        for i in range(0, COLUMN):
            for j in range(0, ROW):
                self.widgt1 = ttk.Label(self.base_frame, anchor="center", text="", font="10", background="white",
                                        padx=10, pady=1)
                self.widgt1.grid(column=i, row=j, padx=1, pady=1)
                self.child_id.append(self.widgt1.winfo_id())

        self.bt1 = ttk.Button(self, text="Button", bg="white")
        self.bt1['command'] = self.bt1_method
        self.bt1.pack(side='bottom')

    def bt1_method(self):
        id_list = self.child_id.copy()
        for child in id_list:
            removeflag = random.randint(0, 1)
            if removeflag == 0:
                id_list.remove(child)

        for child in self.base_frame.winfo_children():
            if child.winfo_id() in id_list:
                child.configure(background="#000000")
            else:
                child.configure(background="#ffffff")

        func1.after(100, self.bt1_method)


if __name__ == "__main__":
    func1 = Function()
    func1.mainloop()