簡體   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