简体   繁体   中英

How to transfer data from one class to another in python using tkinter?

I have no idea how to transfer my data from one class into another. In the code, left below, I have imported some images using the askdirectory command from Tkinter and once I have the directory I import the images. I then get some information about the data, such as the number of extensions and the number of images. (I know these two values will be the same). I should probably mention that this data is found directly in the class PageOne1, it is dealt with in a function that is called from the class PageOne1.

Once this data is defined in a variable I need to be able to use it in a different class which is a frame that is raised higher once the button to import the data is clicked, this is just so that it looks different and the user knows something has happened.

The question is: How can I transfer data from one class to another? EG, in my code, I want to transfer data from class PageOne1 to PageOne2. With this data that is being transfered I want to display it in a label.

#structure for this code NOT created by me - found on stackoverflow.com
import tkinter as tk
from tkinter import filedialog as tkFileDialog
import math, operator, functools, os, glob, imghdr
from PIL import Image, ImageFilter, ImageChops
#fonts
TITLE_FONT = ("Helvetica", 16, "bold","underline") #define font
BODY_FONT = ("Helvetica", 12) #define font
#define app
def show_frame(self, c): #raise a chosen frame
    '''Show a frame for the given class'''
    frame = self.frames[c]
    frame.tkraise()
class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # the container will contain all frames stacked on top of each other, the frame to be displayed will be raised higher
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand=True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        for F in (StartPage, PageOne1, PageOne2,):
            frame = F(container, self)
            self.frames[F] = frame
            # put all of the pages in the same location;
            # the one on the top of the stacking order
            # will be the one that is visible
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, c): #raise a chosen frame
        '''Show a frame for the given class'''
        frame = self.frames[c]
        frame.tkraise()

    def choose(self):
        image_list = []
        extlist = []
        root = tk.Tk()
        root.withdraw()
        file = tkFileDialog.askdirectory(parent=root,title="Choose directory")
        if len(file) > 0:#validate the directory
            print( "You chose %s" % file) #state where the directory is
        for filename in glob.glob(file+"/*"):
            print(filename)
            im=Image.open(filename)
            image_list.append(im)
            ext = imghdr.what(filename)
            extlist.append(ext)
        print("Loop completed")
        extlistlen = len(extlist)
        image_listlen = len(image_list)
                    #these  are the two pieces of data I want to transfer to PageOne2
        self.show_frame(PageOne2)
#frames
class StartPage(tk.Frame): #title/menu/selection page
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="LTC Meteor Detection Program", font=TITLE_FONT) #using labels as they can be updated at any point without updating the GUI, if the data is to be manipulated by the user canvas will be used
        label.pack(side="top", fill="x", pady=10) #pady offers padding between label and GUI border

        button1 = tk.Button(self, text="Import Images",
                            command=lambda: controller.show_frame(PageOne1)) #if button1 chosen, controller.show_frame will raise the frame higher
                            #lambda and controller being used as commands to raise the frames
        button2 = tk.Button(self, text="RMS Base Comparison",
                            command=lambda: controller.show_frame(PageTwo1))
        button3 = tk.Button(self, text="Export Images",
                            command=lambda: controller.show_frame(PageThree1))
        buttonexit = tk.Button(self,text="Quit",
                            command=lambda:app.destroy())
        button1.pack()
        button2.pack()
        button3.pack()
        buttonexit.pack()

class PageOne1(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text = "Import Images", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Select directory",
                           command=controller.choose)
        button.pack()
        button = tk.Button(self, text="Return To Menu",
                           command=lambda: controller.show_frame(StartPage))
        button.pack()



#for reference:
#fileName = tkFileDialog.asksaveasfilename(parent=root,filetypes=myFormats ,title="Save the image as...")

class PageOne2(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text = "Import Images", font=TITLE_FONT)
        label.pack(side="top", fill="x", pady=10)
        label = tk.Label(self, text = ("Number of images: ",image_listlen2," Number of different extensions: ",extlistlen2))
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Return To Menu",
                           command=lambda: controller.show_frame(StartPage))
        button.pack()

if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

You have to keep a reference to the classes. I have eliminated all of the unnecessary code, so just

    self.frames = {}
    for F in (StartPage, PageOne1, PageOne2,):
        frame = F(container, self)
        self.frames[F] = frame

remains. You can then reference data that is a class attribute easily.

class StartPage():
    def __init__(self):
        ## declare and iteger and a string
        self.sp_1=1
        self.sp_2="abc"

class PageOne1():
    def __init__(self):
        ## declare a list and dictionary
        self.sp_1=[1, 2, 3, 4, 5]
        self.sp_2={"abc":1, "def":2}

class YourApp():
    def __init__(self):
        self.frames = {}
        for F in (StartPage, PageOne1):
            frame = F()
            self.frames[F] = frame

        ## print instance attributes from other classes
        for class_idx in self.frames:
            instance=self.frames[class_idx]
            print "\n", instance.sp_1
            print instance.sp_2

YP=YourApp()

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.

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