python-3.x - 使用面向对象的方法在 Tkinter 中的窗口之间传递数据
问题描述
使用 tkinter,我有一个主窗口,它从 TSV 文件读取并创建行及其值的列表,并根据每个项目创建按钮。当您单击一个按钮时,它会打开一个辅助 TopLevel 以编辑您单击的项目。完成后,我想将保存的数据传回主窗口,以便可以将其保存回列表,然后可以将其完全写回 TSV。
我已经搜索并阅读了有关此主题的几篇 SO 和博客文章,最接近的一篇是: How to pass data between top levels in tkinter
但是,在此解决方案中,在与根相同的类中为新(编辑)窗口创建小部件,我想将此工作分离到它自己的类中。问题是,当我将保存的值传递回主窗口时,出现错误(见下文代码)。
这是我正在使用的代码的简化版本(注意,这些类中的每一个都将在它们自己的单独文件中,但为了这个演示,它们被组合在一起。
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
import os
from tkinter import messagebox
class MainApp:
def __init__(self, master):
self.testVar = "none"
self.master = master
ttk.Button(self.master, text = "Open Window", command=lambda: NewWindow(self.master)).pack()
class NewWindow(Toplevel):
def __init__(self, master = None):
super().__init__(master = master)
self.title("New Window")
self.geometry("200x200")
label = Label(self, text ="This is a new Window")
label.pack()
ttk.Button(self, text = "Save", command=lambda: self.SaveData()).pack()
def SaveData(self):
messagebox.showinfo(title=None, message="Save complete: " + self.master.testVar)
def main():
os.system('cls') # on windows
root = Tk()
MainApp(root)
root.mainloop()
if __name__ == "__main__": main()
这是错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python39\lib\tkinter\__init__.py", line 1885, in __call__
return self.func(*args)
File "C:\repos\legend-bowl\test.py", line 22, in <lambda>
ttk.Button(self, text = "Save", command=lambda: self.SaveData()).pack()
File "C:\repos\legend-bowl\test.py", line 25, in SaveData
messagebox.showinfo(title=None, message="Save complete: " + self.master.testVar)
File "C:\Python39\lib\tkinter\__init__.py", line 2347, in __getattr__
return getattr(self.tk, attr)
AttributeError: '_tkinter.tkapp' object has no attribute 'testVar'
我认为 NewWindow 的实例应该能够访问其父级的值,因为父级的实例被传递到其构造函数中。我觉得我错过了一些其他解决方案无法为我回答的简单问题。
- 我应该能够从其孩子的根目录访问吗?
- 显然,可能有更好的方法来处理这个我没有想到的,所以如果你提供它作为解决方案,我仍然想知道#1 的答案
解决方案
问题是self.master
它不是指的实例MainApp
,它指的是根窗口。这是因为您没有传入MainApp
to的实例NewWindow
,而是self.master
引用了 tkinter 定义的变量。
您需要将 to 的实例传递MainApp
给NewWindow
,保存,然后在尝试访问时引用它testVar
。
一种方法是做这样的事情(虽然我个人认为一个函数会比lambda
这里更好):
ttk.Button(self.master, text = "Open Window", command=lambda: NewWindow(self, self.master)).pack()
接下来,您必须定义NewWindow
接受并保存参数,并使用它而不是self.master
class NewWindow(Toplevel):
def __init__(self, mainapp, master = None):
super().__init__(master = master)
self.mainapp = mainapp
...
def SaveData(self):
messagebox.showinfo(title=None, message="Save complete: " + self.mainapp.testVar)
推荐阅读
- java - Docker 文件 - 詹金斯大师 - hudson.util.HudsonFailedToLoad
- python - 我想重塑数据框以使其看起来不同,使行变为列但无法这样做
- date - Vue.js 日期无效
- python - 将终端命令转换为子进程库
- azure - 错误代码 400002:使用 Azure 自定义翻译 API 的类别参数无效
- reactjs - 如何使用 react-navigation 在 React Native 中创建自定义顶部标签栏?
- python - 如何将 Python 数据库中的数据导出到 Excel
- json - 定义结构并将其编组为 json 的问题
- javascript - React useEffect 附加脚本未触发
- python - 熊猫合并不产生数据