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()