我的Python tkinter程序有几个小部件。在1个窗口小部件中创建的数据帧(例如PyDataTest1),其名称由用户选择,也应该在其他窗口小部件中可用。但是,如果小部件有另一个类,那似乎并非如此。我编写了3个python模块:PyDataTestMain,PyDataTest1和PyDataTest2。 PyDataTest2的代码是 - 保持示例简单 - 与PyDataTest1相同(我只用PyDataTest2替换了PyDataTest1)。如果我在小部件p1中保存数据帧,我可以在小部件p3中检索它,但不能在小部件p2和p4中检索它。我需要更改哪些也可以在那里使用它?
'''
PyDataTestMain.py
'''
#%% Import libraries
import tkinter as tk
import tkinter.ttk as ttk
from PyDataTest1 import PyDataTest1
from PyDataTest2 import PyDataTest2
#%% Main class
class PyDataTestMain(ttk.Frame):
def __init__(self, master = None):
# Construct the Frame object.
ttk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.createWidgets()
#%% Create widgets
def createWidgets(self):
# Get top window
self.top = self.winfo_toplevel()
# Make it stretchable
self.top.rowconfigure(0, weight=1)
self.top.columnconfigure(0, weight=1)
# Add several PyDataTest widgets
self.p1 = PyDataTest1(self).grid(row = 0, column = 0, sticky = tk.W, padx =5, pady=5)
self.p2 = PyDataTest2(self).grid(row = 1, column = 0, sticky = tk.W, padx =5, pady=5)
self.p3 = PyDataTest1(self).grid(row = 2, column = 0, sticky = tk.W, padx =5, pady=5)
self.p4 = PyDataTest2(self).grid(row = 3, column = 0, sticky = tk.W, padx =5, pady=5)
#%% Allow the class to run stand-alone.
if __name__ == "__main__":
PyDataTestMain().mainloop()
和
'''
PyDataTest1.py
'''
#%% Import libraries
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox as messagebox
import pandas as pd
#%% Main class
class PyDataTest1(ttk.Frame):
def __init__(self, master = None):
# Construct the Frame object.
ttk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.createWidgets()
def save(self):
var = self.pythonVar.get()
global glb
glb = globals()
glb[var] = pd.DataFrame({'AAA' : [1., 2., 3., 4.], 'BBB' : [43., 32., 21., 10.]})
messagebox.showinfo("Info","pandas dataframe saved as " + var)
def listVars(self):
variables= [var for var in globals() if isinstance(eval(var), pd.core.frame.DataFrame)]
self.comboboxDataframes['values'] = variables
#%% Create widgets
def createWidgets(self):
# Get top window
self.top = self.winfo_toplevel()
# Make it stretchable
self.top.rowconfigure(0, weight=1)
self.top.columnconfigure(0, weight=1)
# Allow to enter a name and save the data in the base workspace
ttk.Label(self, text = "Variable").grid(row = 0, column = 0, sticky = tk.W, padx =5, pady=5)
self.pythonVar = tk.StringVar()
self.pythonVar.set('d')
ttk.Entry(self, textvariable=self.pythonVar).grid(row = 0, column = 1, sticky = tk.W, padx =5, pady=5)
# Save button
ttk.Button(self, text = "Save", command=self.save).grid(row = 0, column = 2, sticky = tk.W, padx =5, pady=5)
# Combobox showing dataframes stored
ttk.Label(self, text = "Dataframes").grid(row = 1, column = 0, sticky = tk.W, padx =5, pady=5)
self.comboboxDataframes = ttk.Combobox(self, postcommand=self.listVars)
self.comboboxDataframes.grid(row = 1, column = 1, sticky = tk.W, padx =5, pady=5)
#%% Allow the class to run stand-alone.
if __name__ == "__main__":
PyDataTest1().mainloop()
我调整了代码并将所有内容放在一个文件中。
'''
PyDataTestMain.py
'''
#%% Import libraries
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox as messagebox
import pandas as pd
#%% Main class
class PyDataTestMain(ttk.Frame):
def __init__(self, master = None):
# Construct the Frame object.
ttk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.createWidgets()
#%% Create widgets
def createWidgets(self):
# Get top window
self.top = self.winfo_toplevel()
# Make it stretchable
self.top.rowconfigure(0, weight=1)
self.top.columnconfigure(0, weight=1)
# Add several PyDataTest widgets
self.p1 = PyDataTest1(self)
self.p1.grid(row = 0, column = 0, sticky = tk.W, padx =5, pady=5)
self.p2 = PyDataTest2(self)
self.p2.grid(row = 1, column = 0, sticky = tk.W, padx =5, pady=5)
self.p3 = PyDataTest1(self)
self.p3.grid(row = 2, column = 0, sticky = tk.W, padx =5, pady=5)
self.p4 = PyDataTest2(self)
self.p4.grid(row = 3, column = 0, sticky = tk.W, padx =5, pady=5)
class PyDataTest1(ttk.Frame):
def __init__(self, master = None):
# Construct the Frame object.
ttk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.createWidgets()
def save(self):
var = self.pythonVar.get()
#global glb
#glb = globals()
self.glb = {}
self.glb[var] = pd.DataFrame({'AAA' : [1., 2., 3., 4.], 'BBB' : [43., 32., 21., 10.]})
messagebox.showinfo("Info","pandas dataframe saved as " + var)
def listVars(self):
#variables= [var for var in globals() if isinstance(eval(var), pd.core.frame.DataFrame)]
variables= [var for var in self.glb() if isinstance(eval(var), pd.core.frame.DataFrame)]
self.comboboxDataframes['values'] = variables
#%% Create widgets
def createWidgets(self):
# Get top window
self.top = self.winfo_toplevel()
# Make it stretchable
self.top.rowconfigure(0, weight=1)
self.top.columnconfigure(0, weight=1)
# Allow to enter a name and save the data in the base workspace
ttk.Label(self, text = "Variable").grid(row = 0, column = 0, sticky = tk.W, padx =5, pady=5)
self.pythonVar = tk.StringVar()
self.pythonVar.set('d')
ttk.Entry(self, textvariable=self.pythonVar).grid(row = 0, column = 1, sticky = tk.W, padx =5, pady=5)
# Save button
ttk.Button(self, text = "Save", command=self.save).grid(row = 0, column = 2, sticky = tk.W, padx =5, pady=5)
# Combobox showing dataframes stored
ttk.Label(self, text = "Dataframes").grid(row = 1, column = 0, sticky = tk.W, padx =5, pady=5)
self.comboboxDataframes = ttk.Combobox(self, postcommand=self.listVars)
self.comboboxDataframes.grid(row = 1, column = 1, sticky = tk.W, padx =5, pady=5)
class PyDataTest2(ttk.Frame):
def __init__(self, master = None):
# Construct the Frame object.
ttk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.createWidgets()
def save(self):
var = self.pythonVar.get()
#global glb
#glb = globals()
glb = {}
glb[var] = pd.DataFrame({'AAA' : [1., 2., 3., 4.], 'BBB' : [43., 32., 21., 10.]})
messagebox.showinfo("Info","pandas dataframe saved as " + var)
def listVars(self):
variables= [var for var in globals() if isinstance(eval(var), pd.core.frame.DataFrame)]
self.comboboxDataframes['values'] = variables
#%% Create widgets
def createWidgets(self):
# Get top window
self.top = self.winfo_toplevel()
# Make it stretchable
self.top.rowconfigure(0, weight=1)
self.top.columnconfigure(0, weight=1)
# Allow to enter a name and save the data in the base workspace
ttk.Label(self, text = "Variable").grid(row = 0, column = 0, sticky = tk.W, padx =5, pady=5)
self.pythonVar = tk.StringVar()
self.pythonVar.set('d')
ttk.Entry(self, textvariable=self.pythonVar).grid(row = 0, column = 1, sticky = tk.W, padx =5, pady=5)
# Save button
ttk.Button(self, text = "Save", command=self.save).grid(row = 0, column = 2, sticky = tk.W, padx =5, pady=5)
# Combobox showing dataframes stored
ttk.Label(self, text = "Dataframes").grid(row = 1, column = 0, sticky = tk.W, padx =5, pady=5)
self.comboboxDataframes = ttk.Combobox(self, postcommand=self.listVars)
self.comboboxDataframes.grid(row = 1, column = 1, sticky = tk.W, padx =5, pady=5)
#%% Allow the class to run stand-alone.
if __name__ == "__main__":
PyDataTestMain().mainloop()
问题是你有模块中的代码,你使用globals()
但globals()
在模块内部提供全局变量,而不是在完整程序中。
在主文件中使用字典来保存数据 - 它可以是主类中的全局字典或字典
self.all_dfs = {}
并将此字典作为参数发送给其他类
self.p1 = PyDataTest1(self, self.all_dfs)
self.p2 = PyDataTest2(self, self.all_dfs)
卖弄.朋友
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox as messagebox
import pandas as pd
from PyDataTest1 import PyDataTest1
from PyDataTest2 import PyDataTest2
class PyDataTestMain(ttk.Frame):
def __init__(self, master=None):
# Construct the Frame object.
ttk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.all_dfs = {
# example dataframe at start
#'a': pd.DataFrame(),
#'b': pd.DataFrame(),
}
self.createWidgets()
#%% Create widgets
def createWidgets(self):
# Get top window
self.top = self.winfo_toplevel()
# Make it stretchable
self.top.rowconfigure(0, weight=1)
self.top.columnconfigure(0, weight=1)
# Add several PyDataTest widgets
self.p1 = PyDataTest1(self, self.all_dfs)
self.p1.grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
self.p2 = PyDataTest2(self, self.all_dfs)
self.p2.grid(row=1, column=0, sticky=tk.W, padx=5, pady=5)
self.p3 = PyDataTest1(self, self.all_dfs)
self.p3.grid(row=2, column=0, sticky=tk.W, padx=5, pady=5)
self.p4 = PyDataTest2(self, self.all_dfs)
self.p4.grid(row=3, column=0, sticky=tk.W, padx=5, pady=5)
#---
PyDataTestMain().mainloop()
py data test1.朋友
import tkinter as tk
import tkinter.ttk as ttk
import tkinter.messagebox as messagebox
import pandas as pd
class PyDataTest1(ttk.Frame):
def __init__(self, master=None, dfs=None):
# Construct the Frame object.
ttk.Frame.__init__(self, master)
self.grid(sticky=tk.N+tk.S+tk.E+tk.W)
self.createWidgets()
self.dfs = dfs
if self.dfs is None:
raise("Need DataFrames dictionary")
def save(self):
var = self.pythonVar.get()
self.dfs[var] = pd.DataFrame({'AAA' : [1., 2., 3., 4.], 'BBB' : [43., 32., 21., 10.]})
messagebox.showinfo("Info","pandas dataframe saved as " + var)
def listVars(self):
self.comboboxDataframes['values'] = list(self.dfs.keys())
#%% Create widgets
def createWidgets(self):
# Get top window
self.top = self.winfo_toplevel()
# Make it stretchable
self.top.rowconfigure(0, weight=1)
self.top.columnconfigure(0, weight=1)
# Allow to enter a name and save the data in the base workspace
ttk.Label(self, text = "Variable").grid(row = 0, column = 0, sticky = tk.W, padx =5, pady=5)
self.pythonVar = tk.StringVar()
self.pythonVar.set('d')
ttk.Entry(self, textvariable=self.pythonVar).grid(row = 0, column = 1, sticky = tk.W, padx =5, pady=5)
# Save button
ttk.Button(self, text = "Save", command=self.save).grid(row = 0, column = 2, sticky = tk.W, padx =5, pady=5)
# Combobox showing dataframes stored
ttk.Label(self, text = "Dataframes").grid(row = 1, column = 0, sticky = tk.W, padx =5, pady=5)
self.comboboxDataframes = ttk.Combobox(self, postcommand=self.listVars)
self.comboboxDataframes.grid(row=1, column=1, sticky=tk.W, padx=5, pady=5)