在循环中创建可互相调用的Tkinter按钮实现帧切换问题求助
问题根源
你的代码核心问题出在按钮command参数的赋值逻辑:
command = raise_frame(winlist[x+1])
这行代码会在循环创建按钮时立即执行raise_frame函数,而不是把这个调用绑定为按钮点击时的触发事件。等你实际点击按钮时,command对应的是函数执行后的返回值(也就是None),自然不会有任何效果。
修复方案
有两种常用方案可以解决这个问题:
方案1:使用lambda匿名函数延迟执行
通过lambda把函数调用包装成回调,同时用x=x固化当前循环的变量值,避免闭包引用问题:
d["button{0}".format(x)] = Button(winlist[x], text = "button{0}".format(x), command = lambda x=x: raise_frame(winlist[x+1]))
方案2:使用functools.partial绑定参数
偏函数可以提前把参数绑定到目标函数上,返回新的无参回调,可读性更高:
- 先在代码顶部导入partial:
from functools import partial - 修改command赋值逻辑:
d["button{0}".format(x)] = Button(winlist[x], text = "button{0}".format(x), command = partial(raise_frame, winlist[x+1]))
修改后完整可运行代码
from tkinter import * from functools import partial # 用方案2的话需要导入,用方案1可以删掉这行 ## Define root and geometry root = Tk() root.geometry('200x200') # Define Frames winlist = [Frame(root, bg='red'), Frame(root, bg='green'), Frame(root, bg='blue')] # Configure Rows root.grid_rowconfigure(0, weight = 1) root.grid_columnconfigure(0, weight = 1) # Place Frames for window in winlist: window.grid(row=0, column = 0, sticky = 'news') # Raises first window 'To the top' winlist[0].tkraise() # Function to raise 'window' to the top def raise_frame(window): window.tkraise() d = {} for x in range(0, 3): d["label{0}".format(x)] = Label(winlist[x], text = "label{0}".format(x)) d["label{0}".format(x)].pack(side=TOP) if x <=1: # 方案1写法: # d["button{0}".format(x)] = Button(winlist[x], text = "button{0}".format(x), command = lambda x=x: raise_frame(winlist[x+1])) # 方案2写法: d["button{0}".format(x)] = Button(winlist[x], text = "button{0}".format(x), command = partial(raise_frame, winlist[x+1])) d["button{0}".format(x)].pack(side=TOP) root.mainloop()
另外原代码里的count变量是冗余的,直接用循环变量x判断即可。
内容的提问来源于stack exchange,提问作者tkirk1222
相关产品推荐
相关产品推荐

