欢迎访问 如意编程网!

如意编程网

当前位置: 首页 > 编程语言 > python >内容正文

python

Python tkinter多窗口的交互问题:子窗口无法获取数据

发布时间:2024/5/15 python 2 豆豆
如意编程网 收集整理的这篇文章主要介绍了 Python tkinter多窗口的交互问题:子窗口无法获取数据 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

Python tkinter多窗口的交互问题:子窗口无法获取数据

tkinter第二个、第三个子窗口数据不能交互响应的解决方法

先说结论:第二个、第三个子窗口生成时,不能用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,可用于arraytf_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,可用于arraytf_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,功能不能实现。而将此段代码放于主窗口的某个位置而不弹出新窗口的话,则功能能够实现。

问题分析

  • 经反复测试,代码功能没有问题。我一度认为是,调用后台函数时,后台函数使用变量的生存周期问题,“在次脚本中tf_radva不能指向对应radio的variable(或者说,这种指向是临时性的,因为次脚本的函数生存周期是临时性,临时性的内存分配,在窗口响应时,该临时内存存储地址未持续到响应事件进行时却已结束)”,——如果说是变量生存周期的问题,那么每次点击radio时,却有事件的响应,每次都打印99,而不是不打印。即事件有响应,那么在响应期,变量是生存的——不是该原因。既然不是变量的生存周期问题,而确实tf_radva未指向对应radio的variable,即程序在执行variable=tf_radva时,未能将tf_radva指向当前窗口radio的变量,而此问题出现在两个窗口共存的情况下。或者可以这样认为,系统此时在确认哪一个是“活跃窗口”发生了问题,需要确定哪一个窗口是active的。
  • 耗费了一上午的时间,经反复查阅与搜索论坛,发现问题所在。将子窗口生成时代码改为tk.Toplevel()即可
  • win_person = tk.Toplevel() # 待详细设置person属性的子窗口

    ——Toplevel(顶级窗口)组件是一个独立的顶级窗口,这种窗口通常拥有标题栏、边框等部件。
    ——何时使用 Toplevel 组件?
    ——Toplevel 组件通常用在显示额外的窗口、对话框和其他弹出窗口上。
    ——Tkinter Toplevel:顶层部件的工作,直接由窗口管理器管理的窗口。他们不必在它们上面的父widget

    参考博文

    参考博文
    https://blog.csdn.net/liyuan3970/article/details/82874653
    Toplevel(顶层)
    https://blog.csdn.net/m0_37264397/article/details/79101630

    总结

    以上是如意编程网为你收集整理的Python tkinter多窗口的交互问题:子窗口无法获取数据的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得如意编程网网站内容还不错,欢迎将如意编程网推荐给好友。