tkinter循环创建Radiobutton时command函数仅最后一个生效问题咨询
问题根因
你在循环调用pins()方法时,所有控件和变量都绑定到了MSM类的同一个实例属性上(比如self.var_wiretype、self.R1_discipline),每一轮循环都会覆盖上一轮的属性值,最终实例里只保留最后一个port对应的控件和变量,所以点击任意frame的单选按钮,操作的都是最后一组属性。
解决方案
将每个port对应的frame、控件、变量、回调逻辑封装为独立的子类,每个port对应一个子类实例,各自维护自身的属性,避免互相覆盖。
修改后完整代码
import tkinter as tk from tkinter import ttk, Frame, BOTH, LEFT, Canvas, IntVar, Radiobutton # 新增PortFrame子类,每个port对应一个独立实例 class PortFrame(tk.Frame): def __init__(self, parent, port, *args, **kwargs): super().__init__(parent, *args, **kwargs) self.pack(fill='both', expand=1) # 每个port实例自己维护变量和控件,不会互相覆盖 self.var_wiretype = IntVar() self.R1_wiretype = Radiobutton(self, text=("wire", port), variable=self.var_wiretype, value=1, command=self.sel_wiretype_1) self.R1_wiretype.grid(row=1, column=1, sticky='W') self.R2_wiretype = Radiobutton(self, text=("wreal", port), variable=self.var_wiretype, value=2, command=self.sel_wiretype_1) self.R2_wiretype.grid(row=1, column=2, sticky='W') self.var_discipline = IntVar() self.R1_discipline = Radiobutton(self, text="logic", variable=self.var_discipline, value=1) self.R1_discipline.grid(row=2, column=1, sticky='W') self.R2_discipline = Radiobutton(self, text="vreal", variable=self.var_discipline, value=2) self.R2_discipline.grid(row=2, column=2, sticky='W') self.R3_discipline = Radiobutton(self, text="ireal", variable=self.var_discipline, value=3) self.R3_discipline.grid(row=2, column=3, sticky='W') self.R4_discipline = Radiobutton(self, text="other", variable=self.var_discipline, value=4) self.entry1 = ttk.Entry(self, width=10) self.entry1.grid(row=3, column=2) self.R4_discipline.grid(row=3, column=1, sticky='W') def sel_wiretype_1(self): # 回调只操作当前实例自身的控件,不会影响其他port if self.var_wiretype.get() == 1: self.R1_discipline['state'] = 'active' self.R2_discipline['state'] = 'disabled' self.R3_discipline['state'] = 'disabled' self.var_discipline.set(1) else: self.R1_discipline['state'] = 'disabled' self.R2_discipline['state'] = 'active' self.R3_discipline['state'] = 'active' self.var_discipline.set(2) class MSM: def __init__(self, top): self.top = top # 创建主框架 self.main_frame = Frame(self.top, width=50, height=100, bd=1) self.main_frame.pack(fill=BOTH, expand=1) # 创建画布 self.my_canvas = Canvas(self.main_frame) self.my_canvas.pack_propagate(0) self.my_canvas.pack(side=LEFT, fill=BOTH, expand=1) self.second_frame = Frame(self.my_canvas) self.second_frame.pack(fill=BOTH, expand=1) # 修复原代码未pack的问题 port_str = ['port1', 'port2', 'port3', 'port4', 'port5'] # 替换为你实际的port值 # 每个port创建独立的PortFrame实例 for port in port_str: PortFrame(self.second_frame, port) if __name__ == "__main__": root = tk.Tk() app = MSM(root) root.mainloop()
关键修改说明
- 新增
PortFrame子类封装单port的所有逻辑,实例属性互不覆盖 - 修复原代码中
second_frame未pack、frame_portdetails_top未定义的错误 - 回调方法现在只操作当前实例自身的控件,不会串到其他port的组件
内容的提问来源于stack exchange,提问作者na lolig
相关产品推荐
相关产品推荐

