My Python tkinter program has several widgets. Dataframes created in 1 widget(eg PyDataTest1), with a name chosen by the user, should also be available in the other widgets. But it seems that's not the case if the widgets have another class. I wrote 3 python modules: PyDataTestMain, PyDataTest1 and PyDataTest2. The code for PyDataTest2 is - to keep the example simple - the same as for PyDataTest1 (I only replaced PyDataTest1 by PyDataTest2). If I save a dataframe in widget p1, I can retrieve it in widget p3, but not in widget p2 and p4. What do I need to change to have it also available there ?
'''
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()
and
'''
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()
I adapted the code and put everything in one file.
'''
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()
Problem is that you have code in modules and you use globals()
But globals()
gives global variables inside module, not in full program.
In main file use dictionary to keep data - it can be global dictionary or dictionary in main class
self.all_dfs = {}
and send this dictionary to other classes as argument
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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.