【发布时间】:2017-12-30 09:09:06
【问题描述】:
我的 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()
【问题讨论】:
-
如果你使用
self.p3 = PyDataTest1(self).grid(),那么你会在self.p3中得到None,因为grid()返回None。如果您需要self.p3,那么您必须分两行完成self.p3 = PyDataTest1(self)和self.p3.grid() -
在小部件 p3 中,我已经可以访问保存在小部件 p1 中的数据框。在小部件 p2 和 p4 中我没有。但我会按照你的建议写。如何将信息从 p1 传递到 p2 ?
-
而不是使用
globals()创建变量,您应该使用全局字典glb = {},然后在类glb[var] =中不使用globals() -
myabe 您可以访问,因为您使用
globals()- 但不是首选。 Python 使用字典以字符串为键来保存数据。 -
如果
PyDataTest2和PyDataTest2有相同的代码,那么如果可以使用PyDataTest1,为什么要使用PyDataTest2
标签: python tkinter parameter-passing