for循环基于SQLite创建Tkinter Checkbutton始终返回false问题
问题根源
你的代码存在两个核心错误,直接导致变量覆盖、状态读取异常:
- 循环内每次创建的
StringVar()实例没有做持久化保存:for循环每轮都会重新给局部变量var赋值,循环结束后var仅指向最后一轮创建的变量,之前生成的所有关联变量因为没有被引用,既无法被外部访问,还会被Python自动回收,对应Checkbutton的状态自然无法正常读取 - 缩进逻辑错误:
pastedids函数、showidbtn按钮都定义在selectcoins()函数外部,本身没有权限访问函数内部创建的selectframe容器和循环内生成的变量,运行时会直接抛出名称不存在的错误,就算不报错也只能读到最后一个被覆盖的var值
修复方法
- 在循环开始前初始化一个列表/字典,专门存储每个Checkbutton对应的
StringVar实例,避免变量被覆盖、回收 - 把
pastedids函数、展示ID的按钮挪到selectcoins()函数内部,保证能访问到存储变量的容器 - 读取选中值时遍历所有存储的变量,收集所有处于选中状态的ID,不要只读取单个变量的值
修复后的可运行代码如下:
def selectcoins(): selectframe = LabelFrame(avreadermain, text='Select Coins') selectframe.grid(row=1,column=0,padx=20,pady=15,sticky=W+E) conn = sqlite3.connect('coinlist.db') cursor = conn.cursor() cursor.execute('SELECT *, oid FROM coins') fetchedcoins = cursor.fetchall() conn.close() # 用完及时关闭数据库连接 # 初始化列表存储每个复选框的关联变量 check_vars = [] for coins in fetchedcoins: coinid = coins[1] coinname = coins[0] var = StringVar() c = Checkbutton(selectframe, text=coinname, variable=var, onvalue=coinid, offvalue='false') c.deselect() c.pack(anchor=W) # 把当前变量存入列表,避免被覆盖回收 check_vars.append(var) def pastedids(): # 遍历所有变量,收集选中的ID selected_ids = [v.get() for v in check_vars if v.get() != 'false'] # 清空之前的展示内容,避免重复堆叠控件 for widget in selectframe.winfo_children(): if isinstance(widget, Label): widget.destroy() coinids = Label(selectframe, text=f"选中的ID:{', '.join(selected_ids)}") coinids.pack(pady=5) showidbtn = Button(selectframe,text='show IDs',command=pastedids) showidbtn.pack(pady=5)
额外说明
如果你需要在selectcoins()函数外部读取选中的加密货币ID,可以把check_vars声明为全局变量,或者绑定到Tk窗口实例的属性上,就能跨作用域访问所有复选框的状态了。
内容的提问来源于stack exchange,提问作者Gabe Itch
相关产品推荐
相关产品推荐

