Pass data frame through Tkinter classes

前端 未结 2 2051
长发绾君心
长发绾君心 2021-02-19 00:20

I am using Python 2.7 and Tkinter. I am almost new to Object Oriented programs. I have a long program with many Tkinter windows and at some point I ask the user to load an Excel

相关标签:
2条回答
  • 2021-02-19 00:44

    There are a few things that are causing issues with your program from running properly.

    The first thing I noticed is the use of global variables. This can be avoided with the use of class attributes.

    For the 2 variables you have just below the line class gui(tk.Tk): you need to move them to the __init__ section so those variables can be instantiated. Also you need to make them into class attributes so other methods or even other classes can interact with them. We can do this by adding the self. prefix to the variable names.

    Something like the below:

    self.data = pd.DataFrame([])
    self.filename = ""
    

    To access the methods/attributes of the gui class you need to pass the object of the gui class to the other classes working with it.

    statusText in your code is not defined so set() wont work here. Just add self.statusText as a class attribute.

    Some of your widgets do not need to be assigned to a variable name as no editing is being done to them. For example:

    label = tk.Label(self, text="Please load a file: ")
    label.pack()
    

    This can be simply changed to:

    tk.Label(self, text="Please load a file: ").pack()
    

    This will help reduce the amount of code you are writing and keep the name space cleaner.

    There are a few ways to correct all this but the easiest way is to move this code into one class. There is not a good reason with the code you have presented to have several frames separated from the main gui class.

    The below code is a rewritten version of your code using one class to accomplish what appears to be the task your code is trying to accomplish and reducing the amount of code needed by around 30+ lines. I am sure it can be refined further but this example should be helpful.

    import Tkinter as tk
    import pandas as pd
    import tkFileDialog
    
    class gui(tk.Frame):
    
    
        def __init__(self, master, *args, **kwargs):
            tk.Frame.__init__(self, master, *args, **kwargs)
    
            self.master = master
            self.data = pd.DataFrame([])
            self.filename = ""
            self.strat_columns = []
    
            self.main_frame()
            self.first_frame()
            self.mainframe.tkraise()
    
        def get_page(self, page_class):
            return self.frames[page_class]
    
        def main_frame(self):
            self.mainframe = tk.Frame(self.master)
            self.mainframe.grid(row=0, column=0, sticky="nsew")
    
            tk.Button(self.mainframe, text="New window", 
                      command=lambda: self.firstframe.tkraise()).pack()
    
    
        def first_frame(self):
            self.firstframe = tk.Frame(self.master)
            self.firstframe.grid(row=0, column=0, sticky="nsew")
    
            self.statusText = tk.StringVar()
            self.statusText.set("Press Browse button and browse for file, then press the Go button")
            label = tk.Label(self.firstframe, text="Please load a file: ").pack()
            self.first_frame_entry = tk.Entry(self.firstframe, width=50)
            self.first_frame_entry.pack()
            tk.Button(self.firstframe, text="Go", command=self.button_go_callback).pack()
            tk.Button(self.firstframe, text="Browse", command=self.button_browse_callback).pack()
            self.message = tk.Label(self.firstframe, textvariable=self.statusText)
            self.message.pack()
    
    
        def button_browse_callback(self):
            self.filename = tkFileDialog.askopenfilename()
            self.first_frame_entry.delete(0, tk.END)
            self.first_frame_entry.insert(0, self.filename)
    
        def button_go_callback(self):
            self.data = pd.read_excel(self.filename)
    
    
    if __name__ == "__main__":
        root = tk.Tk()
        root.title("TEST")
        my_gui = gui(root)
        root.mainloop()
    
    0 讨论(0)
  • 2021-02-19 00:54

    in my opinion your are tying too much the data and the GUI. What if in the future you want to display something else? I would use a more generic approach: I would a create a DataProvider class that would read and return the data for you:

    Data Provider

    import pandas as pd
    
        class DataProvider(object):
    
            def __init__(self):
                self._excel = {}
                self._binary = {}
    
            def readExcel(self, filename):
                self._excel[filename] = pd.read_excel(filename)
    
            def excel(self):
                return self._excel
    
            def readBinary(self, filename):
                self._binary[filename] = open(filename,"rb").read()
    
            def binary(self):
                return self._binary
    

    Using this class you can obtain the data that you can present in your GUI:

    gui.py

    from Tkinter import *
    from DataProvider import *
    import binascii
    
    #example data
    dp = DataProvider()
    dp.readExcel("file.xlsx")
    dp.readBinary("img.png")
    
    
    root = Tk()
    frame = Frame(root)
    frame.pack()
    
    bottomframe = Frame(root)
    bottomframe.pack( side = BOTTOM )
    
    w = Label(bottomframe, text=dp.excel()["file.xlsx"])
    w.pack()
    
    
    w = Label(bottomframe, text=binascii.hexlify(dp.binary()["img.png"][:5]))
    w.pack()
    
    root.mainloop()
    

    If all works well you should have a small GUI showing the content of the Excel file and the first few bytes of the image.

    Let me know if all works fine or if you need more info.

    Thanks

    0 讨论(0)
提交回复
热议问题