Home > OS >  Reaching the parent's parent in Tkinter
Reaching the parent's parent in Tkinter

Time:07-22

Suppose I have a tkinter app with the following layout.

Tkinter App Layout

I have used an object-oriented hierarchical model such that the classes are instantiated like this:

MainWindow
├── OptionsFrame
│   ├── DataFrame
│   ├── MetaFrame
│   └── SaveFrame
└── PlotFrame

I want to be able to use the plot button within the SaveFrame to run a function which will plot using a FigureCanvasTkAgg canvas object.

I am struggling to see how I can reach the PlotFrame from within the SaveFrame.

So far I have been using a main parameter in my class declarations, i.e.

class SaveFrame(ttk.Frame):
    def __init__(self, main, *args, **kwargs):
        super().__init__(main, *args, **kwargs)
        self.main = main

which will allow me to go up one level of the hierarchy to the OptionsFrame, but what I need to do is go from

SaveFrame -> OptionsFrame -> MainWindow -> PlotFrame

I don't really know how this is possible.

Thanks

CodePudding user response:

Standard widgets get parent as first argument and keep it in self.master - you don't need self.main.

Using self.master you can access parent and using self.master.master can acess grandparent, etc. - and this grandparent can be your MainWindow.

If MainWindow keeps PlotFrame as i.e. self.plot_frame then SaveFrame may needs

self.master.master.plot_frame

EDIT:

Other method is to send PlotFrame (self.plot_frame) as argument to OptionsFrame and it should send it as argument to SaveFrame and it will have direct access to PlotFrame

class SaveFrame(ttk.Frame):
    def __init__(self, main, plot_frame, *args, **kwargs):
        super().__init__(main, *args, **kwargs)
        self.main = main
        self.plot_frame = plot_frame

class OptionsFrame(ttk.Frame):
    def __init__(self, main, plot_frame, *args, **kwargs):
        super().__init__(main, *args, **kwargs)
        self.main = main
        self.save_frame = SaveFrame(main, plot_frame)

# in MainWindow

self.plot_frame = PlotFrame(...)
self.options_frame = OptionsFrame(self, self.plot_frame)

CodePudding user response:

self.winfo_toplevel() will get you to the main window, so the below should do what you need. I find this method much easier than working backwards through .master. Also, if you ever further nest your classes, you will have to add another master to all the master.master.master spots. This is going to get the top level window that the current widget belongs to, and never needs to be modified, regardless of how deep you bury a widget.

root = self.winfo_toplevel()
plot = root.plot_frame  #or whatever you called it
  • Related