简体   繁体   中英

I can't pass parent variables through Tkinter in Python 2.7

First of All, I have to say that I am a beginner in Python, so my code might appears redundant or muddled. I made this code which consists of two classes that are both tkinter frame. The class ExportGUI inherits from Hdf5GUI and is called by the function export . The thing is I am trying to access the parent variable datasetsfilter through a child function but it doesnt work :

# Parent class

class Hdf5GUI(GUI):

    def __init__(self,hdf5w,master):

        # Frame definition
        self.master = master # parent root
        self.hdf5w = hdf5w #root
        self.hdf5w.title('Hdf5 Reader') 
        self.hdf5w.rowconfigure(0,weight=1)
        self.hdf5w.columnconfigure(0,weight=1)
        self.hdf5w.columnconfigure(1,weight=1)

        self.frameDataset = Frame(self.hdf5w,padx=5,pady=5)
        self.frameDataset.grid(row=0,column=0,sticky='wesn')
        self.frameDataset.rowconfigure(1,weight=1)
        self.frameDataset.columnconfigure(0,weight=1)

        self.datasetpath_button = Button(self.frameDataset,text="Export dataset path",command = self.exportDatasetPath)
        self.datasetpath_button.grid(row=0,column=0,columnspan=2,pady=5,sticky='nwe')

        self.dataset_scrollbar = Scrollbar(self.frameDataset)
        self.dataset_scrollbar.grid(row=1,column=1,sticky='esn')

        self.dataset_listbox = Listbox(self.frameDataset,exportselection=0)
        self.dataset_listbox.grid(row=1,column=0,sticky='wesn')
        self.dataset_listbox.bind('<<ListboxSelect>>', self.onSelectDataset)

        self.dataset_listbox.config(yscrollcommand=self.dataset_scrollbar.set)
        self.dataset_scrollbar.config(command=self.dataset_listbox.yview)

        self.datatype_scrollbar = Scrollbar(self.frameDataset)
        self.datatype_scrollbar.grid(row=2,column=1,sticky='esn')

        self.datatype_listbox = Listbox(self.frameDataset,selectmode='extended',exportselection=0)
        self.datatype_listbox.grid(row=2,column=0,sticky='wesn')
#        self.dataset_listbox.bind('<<ListboxSelect>>', self.onSelectDataset)
#        
        self.datatype_listbox.config(yscrollcommand=self.datatype_scrollbar.set)
        self.datatype_scrollbar.config(command=self.datatype_listbox.yview)        



        self.frameFilter = Frame(self.frameDataset)
        self.frameFilter.grid(row=3,column=0,sticky='wen')
        self.frameFilter.columnconfigure(0,weight=1)
        self.frameFilter.columnconfigure(1,weight=1)
        self.frameFilter.columnconfigure(2,weight=1)
        self.frameFilter.columnconfigure(3,weight=1)

        self.filter_label = Label(self.frameFilter,text="Dataset filter")
        self.filter_label.grid(row=0,column=0,columnspan=4,sticky='wen')

        self.filter0 = Listbox(self.frameFilter,exportselection=0)
        self.filter0.grid(row=1,column=0,sticky='wen')
        self.filter0.bind('<<ListboxSelect>>', self.onSelectFilter0)

        self.filter1 = Listbox(self.frameFilter,exportselection=0)
        self.filter1.grid(row=1,column=1,sticky='wen')
        self.filter1.bind('<<ListboxSelect>>', self.onSelectFilter1)

        self.filter2 = Listbox(self.frameFilter,exportselection=0)
        self.filter2.grid(row=1,column=2,sticky='wen')
        self.filter2.bind('<<ListboxSelect>>', self.onSelectFilter2)

        self.filter3 = Listbox(self.frameFilter,exportselection=0)
        self.filter3.grid(row=1,column=3,sticky='wen')

        self.frameFile = Frame(self.hdf5w,padx=5,pady=5)
        self.frameFile.grid(row=0,column=1,sticky='wesn')
        self.frameFile.rowconfigure(1,weight=1)
        self.frameFile.columnconfigure(0,weight=1)

        self.folderPath_button = Button(self.frameFile,text="Open files in directory",command=self.exportFiles)
        self.folderPath_button.grid(row=0,column=0,columnspan=2,pady=5,sticky='wen')

        self.files_listbox = Listbox(self.frameFile,selectmode='extended',exportselection=0)
        self.files_listbox.grid(row=1,column=0,sticky='wesn')

        self.files_scrollbar = Scrollbar(self.frameFile)
        self.files_scrollbar.grid(row=1,column=1,sticky='esn')

        self.files_listbox.config(yscrollcommand=self.files_scrollbar.set)
        self.files_scrollbar.config(command=self.files_listbox.yview)

        self.displayData_button = Button(self.frameFile, text="display dataset", command=self.displayData)
        self.displayData_button.grid(row=2,column=0,columnspan=2,padx=10,pady=5,sticky='wen')


        self.displayTxt_button = Button(self.frameFile, text="Export", command=self.export)
        self.displayTxt_button.grid(row=2,column=1,columnspan=2,padx=10,pady=5,sticky='wen')



#        self.lblFrame = LabelFrame()


        self.hdf5w.protocol("WM_DELETE_WINDOW", self.onClosing)





        self.hdf5w.mainloop()

    def exportDatasetPath(self):

        self.dataset_listbox.delete(0,'end')
        self.filter0.delete(0,'end')
        self.filter1.delete(0,'end')
        self.filter2.delete(0,'end')
        self.filter3.delete(0,'end')

        self.ohdf5 = Hdf5()

        print(self.ohdf5.loadcase_label_list)

        i = 0
        for dataset in self.ohdf5.datasets:
            self.dataset_listbox.insert(i,dataset)
            i+=1

        i = 0
        for item in self.ohdf5.filter0:
            self.filter0.insert(i,item)
            i+=1

    def onSelectDataset(self,evt):

        self.datatype_listbox.delete(0,'end')
        index = self.dataset_listbox.curselection()[0]
        datasetPath = self.dataset_listbox.get(index)

        self.odataset = self.ohdf5.getDataset(datasetPath)

        i=0
        for col in self.odataset.columns:
            self.datatype_listbox.insert(i,col)
            i+=1


    def onSelectFilter0(self,evt):

        self.dataset_listbox.delete(0,'end')
        self.filter1.delete(0,'end')
        self.filter2.delete(0,'end')
        self.filter3.delete(0,'end')

        index = self.filter0.curselection()[0]
        item0 = self.filter0.get(index)


        if item0 == 'NASTRAN':
            i = 0
            for dataset in self.ohdf5.datasets:
                self.dataset_listbox.insert(i,dataset)
                i+=1

        else:

            self.ohdf5.setFilterGroupPath(item0)
            self.ohdf5.setFilterGroup(self.ohdf5.filterGroupPath)

            i = 0
            self.datasetsfilter = self.ohdf5.getDatasets(self.ohdf5.filterGroupPath)
            for dataset in self.datasetsfilter:
                self.dataset_listbox.insert(i,dataset)
                i+=1

            i = 0
            for item in self.ohdf5.filter1:
                self.filter1.insert(i,item)
                i+=1

    def onSelectFilter1(self,evt):

        self.dataset_listbox.delete(0,'end')
        self.filter2.delete(0,'end')
        self.filter3.delete(0,'end')

        index = self.filter0.curselection()[0]
        item0 = self.filter0.get(index)
        index = self.filter1.curselection()[0]
        item1 = self.filter1.get(index)

        self.ohdf5.setFilterGroupPath(item0,item1)
        self.ohdf5.setFilterGroup(self.ohdf5.filterGroupPath)

        i = 0
        self.datasetsfilter = self.ohdf5.getDatasets(self.ohdf5.filterGroupPath)
        print(self.datasetsfilter)
        for dataset in self.datasetsfilter:
            self.dataset_listbox.insert(i,dataset)
            i+=1

        i = 0
        for item in self.ohdf5.filter2:
            self.filter2.insert(i,item)
            i+=1

    def onSelectFilter2(self,evt):

        self.dataset_listbox.delete(0,'end')
        self.filter3.delete(0,'end')

        index = self.filter0.curselection()[0]
        item0 = self.filter0.get(index)
        index = self.filter1.curselection()[0]
        item1 = self.filter1.get(index)
        index = self.filter2.curselection()[0]
        item2 = self.filter2.get(index)

        self.ohdf5.setFilterGroupPath(item0,item1,item2)
        self.ohdf5.setFilterGroup(self.ohdf5.filterGroupPath)

        i = 0
        self.datasetsfilter = self.ohdf5.getDatasets(self.ohdf5.filterGroupPath)
        print(self.datasetsfilter)
        for dataset in self.datasetsfilter:
            self.dataset_listbox.insert(i,dataset)
            i+=1

        i = 0
        for item in self.ohdf5.filter3:
            self.filter3.insert(i,item)
            i+=1

    def exportFiles(self):

        self.files_listbox.delete(0,'end')

        title = 'Choose the working HDF5 directory where there are *.h5 files :'
        Tk().withdraw()
        dirname_root = askdirectory(initialdir=os.getcwd(), title = title)

        self.filePath_list = []

        for folders, subfolders,files in os.walk(dirname_root):
            for f in files:
                ext = os.path.splitext(f)[1]
                if ext == '.h5': self.filePath_list.append(os.path.join(folders,f))

        i = 0
        for path in self.filePath_list:
            self.files_listbox.insert(i,os.path.basename(path))
            i+=1

    def onClosing(self):

#        if tkMessageBox.askokcancel("Quit", "Do you want to quit?"):
        self.hdf5w.destroy()
        self.show(self.master)  

    def displayData(self):
        print('function dislaying datas')
        datas =   self.datatype_listbox.curselection()
        print(datas)
        new_window = Toplevel(self.frameFile)
        w = DisplayDataGUI(new_window, self.odataset, datas)

    def get_datasetsfilter(self):
        return self.datasetsfilter

    def export(self):
        new_window2 = Toplevel(self.frameFile)
        w = ExportGUI(self.hdf5w,new_window2)

So until now my code perfectly works but I had to complete my program with some other functions that I call in ExportGUI . For example export_filter .

#==============================================================================
# Child class   
#==============================================================================



class ExportGUI(Hdf5GUI): 

    def __init__(self,hdf5w, master):

        self.master = master
        self.master.title("Export")
        self.master.geometry('200x200')

        label = Label(self.master, text="Choose the kind of export")
        label.place(x=20, y=0)

        export_selected = Button(self.master, text = 'Export filters',command=self.export_filter)
        export_selected.place(x=20, y=50)

        self.master.mainloop()   

    def export_filter(self):    
        print(self.ohdf5.datatsetsfilter)

But I got the following error :

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\ProgramData\Anaconda2\lib\lib-tk\Tkinter.py", line 1542, in __call__
    return self.func(*args)
  File "GUI\GUI.py", line 397, in export_filter
    print(self.ohdf5.datatsetsfilter)
AttributeError: 'ExportGUI' object has no attribute 'ohdf5'

Neither ohdf5 or datatsetsfilter is known by ExportGUI (I had the same error with self.datatsetsfilter ). Considering this code didnt work I tried to use the super function. I created a function get_datasetsfilter in Hdf5GUI :

 def get_datasetsfilter(self):
        return self.datasetsfilter

and then called it in ExportGUI (I added __metaclass__ = type to fix type prblm in 2.7) :

def export_filter(self):    
        super(ExportGUI, self).get_datasetsfilter

I admit I saw many other exemple with Super but they all seems to be used in __init__ method. However, it still doesnt work. I am now wondering if the error results from my bad comprehension of inheritance or tkinter .

The problem is that you have overwritten the __init__ method from the parent class. Usually what you is first call the __init__ method from the parent class that can be accessed using the super() . So your code should be something like:

class ExportGUI(Parent_Class):

    def __init__(self, hdf5w, master):
        super().__init__(hdf5w, master)
        self.master = master
        self.master.title("Export")
        self.master.geometry('200x200')

UPDATE:

Now that you've cleared certain details I can augment this answer. Notice that the __init__ call from the ExportGUI is now called with two passed arguments, namely hdf5w and master , the first one is needed to successfully call the __init__ from the parent class. Thus you need to change the code in the definiton of Parent_Class where you're creating an instance of ExportGUI , so that a proper value for hdf5w will be passed in -- my guess would be, you want to pass the value from the parent class:

def export(self):
    new_window2 = Toplevel(self.frameFile)
    w = ExportGUI(self.hdf5w, new_window2)

And I can't help but notice, that the arguments passed to Parent_Class.__init__ namely hdf5w and master are not used anywhere. Maybe you want to either save those in variables, for example:

class Parent_Class(GUI):

    def __init__(self,hdf5w,master):
        self.hdf5w = hdf5w
        self.master = master

If those are the same and should be carried across to the ExportGUI they can be simply passed when you're creating an instance in the export function of the Parent_Class . If you don't need them and decide to remove them, make sure to modify the __init__ call of the Parent_Class as well as the super().__init__ call in the ExportGUI .

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