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

Tkinter开发井字棋:如何将按钮作为参数传入函数并解决未定义报错

问题原因

你遇到的name b1 is not defined错误,是因为创建b1按钮的语句里,lambda id=b1: play(id)中的b1还没完成赋值——Python执行到这行代码时,会先解析lambda表达式,此时b1变量还没被定义(按钮对象还没创建完成),所以触发报错。

解决方案

这里给你两种实用的解决方法,都能实现用同一个函数处理所有按钮的点击逻辑:

方法1:先创建按钮,再绑定command

先完成按钮对象的创建,此时b1已经被定义,再给它设置command参数,这样lambda就能正确引用到按钮对象:

import tkinter as tk

app = tk.Tk()
# 假设你已提前加载所需图片
cross = tk.PhotoImage(file="cross.png")
circle = tk.PhotoImage(file="circle.png")
white = tk.PhotoImage(file="white.png")
player = "X"  # 初始玩家

def play(bid):
    global player  # 声明使用全局变量player
    if player == "X":
        bid.config(image=cross)
        player = "O"  # 切换玩家
    else:
        bid.config(image=circle)
        player = "X"

# 先创建按钮,此时b1已定义
b1 = tk.Button(app, text="", image=white)
# 绑定command,lambda直接引用b1
b1.config(command=lambda: play(b1))
b1.grid(column=0, row=0)

# 其他按钮按相同逻辑创建
b2 = tk.Button(app, text="", image=white)
b2.config(command=lambda: play(b2))
b2.grid(column=1, row=0)

app.mainloop()

方法2:用bind绑定点击事件,通过event获取按钮对象

这种方法不需要给每个按钮单独传参,直接通过点击事件的event.widget属性获取被点击的按钮,代码更简洁:

import tkinter as tk

app = tk.Tk()
cross = tk.PhotoImage(file="cross.png")
circle = tk.PhotoImage(file="circle.png")
white = tk.PhotoImage(file="white.png")
player = "X"

def play(event):
    global player
    bid = event.widget  # 获取被点击的按钮对象
    if player == "X":
        bid.config(image=cross)
        player = "O"
    else:
        bid.config(image=circle)
        player = "X"

# 创建按钮时用bind绑定左键点击事件
b1 = tk.Button(app, text="", image=white)
b1.bind('<Button-1>', play)
b1.grid(column=0, row=0)

b2 = tk.Button(app, text="", image=white)
b2.bind('<Button-1>', play)
b2.grid(column=1, row=0)

app.mainloop()

额外注意点

  • 必须在play函数里声明global player,否则无法修改全局的player变量,玩家切换逻辑会失效。
  • 原代码里的两个独立if语句存在逻辑漏洞,改成if-else能确保每次点击只会执行其中一个分支。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:41:40