Tkinter:将绑定分配给由循环函数创建的大量小部件(框架)

问题描述 投票:0回答:1

我正在使用 Python 的 Tkinter 开发一个图库显示工具,其中涉及一次创建大量框架,每个框架包含一个图像。这是通过“while”或“for”循环实现的:

x = 0
while x < 10:
     tk.Frame(r, width=50, height=50, borderwidth=1, relief='solid', bg='purple').pack()
     x+=1

这很有效,因为我不需要将其中的任何内容存储在变量中。然而问题是,我还想将一个事件绑定到这些框架中的每一个,但它无法按预期工作:

import tkinter as tk

r = tk.Tk()

# This function switches the Frame's color
def change_color(wid):
    # This print function shows that only '.!Frame10' is being affected
    print(wid)

    if wid['bg'] == 'purple':
        wid['bg'] = 'green'

    elif wid['bg'] == 'green':
        wid['bg'] = 'purple'

# Frames are created by functions to allow binding & packing using a temporary reference
def frame():
    main = tk.Frame(r, width=50, height=50, borderwidth=1, relief='solid', bg='purple')
    # This bind triggers the function which affects the frame being left-clicked
    main.bind_all('<Button-1>', lambda a: change_color(main) )
    main.pack()

# This loop creates 10 instances of the frame
x = 0
while x < 10:
     frame()
     x+=1

r.mainloop()

预期的结果是,可以左键单击每个单独的帧来切换其颜色,但只有最后一个帧(称为“.!Frame10”)会在单击帧上的任何帧时切换颜色。

我读到您可以使用字典自动将对象/函数存储在变量中,但它似乎不适合我。我制作的这个例子返回“ KeyError: '3' ”,我不明白。

import tkinter as tk

r = tk.Tk()

# This function switches the Frame's color
def change_color(x):
    # This print function shows that only '.!Frame10' is being affected
    print(x)

    if x['bg'] == 'purple':
        x['bg'] = 'green'

    elif x['bg'] == 'green':
        x['bg'] = 'purple'

dic = {}

# This loop creates frames and stores them in the dictionary above.
x = 1
while x < 3:
    dic[str(x)] = tk.Frame(r, width=50, height=50, borderwidth=1, relief='solid', bg='purple')
    dic[str(x)].bind_all('<Button-1>', lambda a: change_color(dic[str(x)]) )
    dic[str(x)].pack()
    x+=1

r.mainloop()

我确实让它与字典一起工作了几次,但它给出了与上面相同的结果;仅更改最后一帧。

如有任何帮助,我们将不胜感激。

python tkinter
1个回答
0
投票

这将解决您的问题:

import tkinter as tk
r = tk.Tk()
r.geometry('500x700')
# This function switches the Frame's color
def change_color(wid):
    current_bg = wid.cget('bg') # use wid.cget()
    if current_bg == 'purple':
        wid.config(bg = 'green') # Use wid.config

    elif current_bg ==  'green': # use wid.cget()
        wid.config(bg = 'purple') # Use wid.config

def create_frames():       
    
    for x in range(10):
        frame = tk.Frame(r, width=50, height=50, borderwidth=1, relief='solid', bg='purple')
        frame.pack()
        # Pass the current frame as a default argument to fix late binding
        frame.bind('<Button-1>', lambda event, current_frame=frame: change_color(current_frame))

           

create_frames()
r.mainloop()
© www.soinside.com 2019 - 2024. All rights reserved.