繁体   English   中英

python tkinter在小部件之间传递数据帧

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM