先说结论:第二个、第三个子窗口生成时,不能用tk.Tk(),而应改为tk.Toplevel(),问题解决。
最近在用tk、ttk开发一个仿真软件时,当在主窗口(tk.Tk()生成)点击相关设置按键时,调用另一模块中的函数(通过import导入),函数执行过程中弹出第二个或更多的子窗口,在子窗口输入数据或点击相关按键时,发现子窗口的交互数据无法获得!而同样的代码段如果放入主窗口则没有问题! 下图为问题出现的场景 点击person行的参数设置,选择自定义模式时,调用另一模块中的函数,弹出新的窗口。 主脚本代码为:
person_par_set = ttk.Combobox(type_table, width=10) # 初始化 person_par_set["values"] = ("Default", "User-defined") person_par_set.current(0) # 选择第一个 def go_person_par_set(*args): # 事件 var_number = eval(number_set.get()) # 将对应的字符型数值转换为数字 var_person_prop = eval(person_prop.get()) var_person_par = person_par_set.get() var_person_label = person_label.cget("text") var_person = {'label': var_person_label, 'prop': var_person_prop, 'par': var_person_par} person_row.set(var_person) # 将字典型以字符串形式赋值给控件型变量 set_person(var_number, var_person) # 调用另一模块中的函数,实现person的设置 person_par_set.bind("<<ComboboxSelected>>", go_person_par_set) # 绑定事件,(下拉列表框被选中时,绑定go()函数)调用的函数代码为:
def set_person(var_number, var_person): # 进行person型成员的设置 person_number = round(var_number * var_person['prop'] * 0.01, 0) # 四舍五入取0位小数 p = int(person_number) if var_person['par'] == "Default": tf_data = np.random.uniform(0, 1, p) # 生成0~1之间,p个均匀分布的随机数 # 为将list中每个数字保留2位,将list转为numpy数组,然后对numpy进行操作,最后将numpy再转为数组。 tf_data = np.array(tf_data) tf_data = np.round(tf_data, 2) # round不能用于list,可用于array tf_data = list(tf_data) np.save('person_par.npy', tf_data) elif var_person['par'] == "User-defined": win_person = tk.Tk() # 待详细设置person属性的子窗口 win_person.title('Person Properties Settings') wid = sub_window(win_person) # 调用sub_window函数,设置窗口,并返回窗口的宽度值 tf_table = ttk.LabelFrame(win_person, text='information set', labelanchor='n') tf_table.grid(column=0, row=3, padx=8, pady=15) # row,column指示相对行号和列号,非绝对位置;padx,y为挂靠坐标位置 tf_radva = tk.IntVar() tf_radva.set(99) def radCall(*args): print(tf_radva.get()) curRad1 = ttk.Radiobutton(tf_table, text="平均分布", value=1, variable=tf_radva, command=radCall) curRad1.grid(column=0, row=0, sticky=tk.W) curRad2 = ttk.Radiobutton(tf_table, text="正态分布", value=2, variable=tf_radva, command=radCall) curRad2.grid(column=0, row=1, sticky=tk.W) tf_data = np.random.normal(0.5, 0.1, p) # 生成0~1之间,p个均匀分布的随机数 # 为将list中每个数字保留2位,将list转为numpy数组,然后对numpy进行操作,最后将numpy再转为数组。 tf_data = np.array(tf_data) tf_data = np.round(tf_data, 2) # round不能用于list,可用于array tf_data = list(tf_data) np.save('person_par.npy', tf_data)弹出设置窗口 上述代码设计为:tf_radva初值设置为99;当radio按钮被选中时,其值(分别为1,2)会赋给tf_radva,通过tf_radva这个IntVar型控件变量指向radio的variable的方式。拟实现的效果为,当选中<平均分布radio>时,打印1;选中<正态分布>时,打印2。而真实情况是,无论选中哪个radio,都打印99,功能不能实现。而将此段代码放于主窗口的某个位置而不弹出新窗口的话,则功能能够实现。
——Toplevel(顶级窗口)组件是一个独立的顶级窗口,这种窗口通常拥有标题栏、边框等部件。 ——何时使用 Toplevel 组件? ——Toplevel 组件通常用在显示额外的窗口、对话框和其他弹出窗口上。 ——Tkinter Toplevel:顶层部件的工作,直接由窗口管理器管理的窗口。他们不必在它们上面的父widget
参考博文 https://blog.csdn.net/liyuan3970/article/details/82874653 Toplevel(顶层) https://blog.csdn.net/m0_37264397/article/details/79101630