You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何定位tkinter按钮数组中被点击的按钮并修改其颜色

问题根因

点击任意按钮都只修改最后一个按钮样式,是Python lambda闭包的典型特性导致的:lambda表达式中引用的循环变量x、y不会在定义时固定值,而是会在实际触发点击时读取变量当前值。等双层循环全部执行完,x和y会停在最后一轮循环的数值上,不管点哪个按钮,传入回调函数的都是最后一组坐标,自然只会操作最后一个创建的按钮。
你之前写的8x8棋盘版本除了上述闭包问题外,回调函数onClick直接写死取tile[-1]也就是按钮列表的最后一个元素,逻辑上也必然只会修改最后一个按钮。

修复方案

核心是给每个按钮的回调函数提前绑定当前循环轮次的坐标值,最简便的写法是利用lambda的默认参数——默认参数会在函数定义时就固定取值,不会随循环变量变动。

修复后的60*20按钮阵列代码

from tkinter import *

class testClass:
    def main(self):
        root = Tk()
        frame=Frame(root)
        frame.grid(row=0,column=0)

        self.btn=  [[0 for x in range(20)] for x in range(60)] 
        for x in range(60):
            for y in range(20):
                # 新增x=x、y=y默认参数,绑定当前循环的坐标值
                self.btn[x][y] = Button(frame,command= lambda x=x, y=y: self.color_change(x,y))
                self.btn[x][y].grid(column=x, row=y)

        root.mainloop()

    def color_change(self,x,y):
        self.btn[x][y].config(bg="red")

testMain = testClass()
testMain.main()

修复后的8x8棋盘代码

from tkinter import *

root = Tk()

wd = Frame(root, width = "500", height = "500", bg = "brown")
wd.pack( padx = 5, pady = 5)

tile = {}

# 回调接收当前按钮的坐标
def onClick(x, y):
    tile[(x,y)].config(bg = "green") 

for row_idx in range(8):
    for col_idx in range(8):
        if 2 <= row_idx <=4:
            btn = Button(wd, width = 2, height = 1, command = lambda x=row_idx, y=col_idx: onClick(x,y))
            btn.grid(padx = 0.5, pady = 0.5, row = row_idx, column = col_idx)
            tile[(row_idx, col_idx)] = btn
            
        elif 0 <= row_idx <=1:
            btn = Button(wd, width = 2, height = 1, text = "O", fg = "red", command = lambda x=row_idx, y=col_idx: onClick(x,y))
            btn.grid(padx = 0.5, pady = 0.5, row = row_idx, column = col_idx)
            tile[(row_idx, col_idx)] = btn
            
        elif 6 <= row_idx <=7:
            btn = Button(wd, width = 2, height = 1, text = "O", fg = "blue", command = lambda x=row_idx, y=col_idx: onClick(x,y))
            btn.grid(padx = 0.5, pady = 0.5, row = row_idx, column = col_idx)
            tile[(row_idx, col_idx)] = btn
            
root.mainloop()

注意:不要把mainloop()的返回值赋值给Tk实例变量,会覆盖原窗口对象导致异常,直接调用mainloop()即可。

内容的提问来源于stack exchange,提问作者Arran McLoughlin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:39:15