[英]python tkinter passing dataframes between widgets
我的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)
main.py
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()
PyDataTest1.py
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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.