Search code examples
pythonuser-interfacetkinterttk

Access specific ttk.Notebook tab from another class


I have two classes in one file, one for the main gui and the other for the little settings gui.

from tkinter import *
import tkinter as tk

class Class1:
    def __init__(self, mainwindow):
        self.mainwindow = mainwindow
        self.mainwindow.title("Assistant")
        self.mainwindow.geometry("550x400")

        # -- MenuBar --
        MenuBar = Menu(self.mainwindow)

        # FirstMenu
        FirstMenu = Menu(MenuBar, tearoff=False)
        FirstMenu.add_command(label="Settings", command=self.OpenInfo)
    
        self.mainwindow.config(menu=MenuBar)

    def OpenInfo(self):
        self.OpenSettings = Toplevel(self.mainwindow)
        self.app = SettingsGUI(self.OpenSettings)


        # -- MISSING CODE HERE --



class SettingsGUI:
    def __init__(self, settingswindow):
        self.settingswindow = settingswindow
        self.settingswindow.title("Settings")
        self.settingswindow.geometry("300x250")
        
        self.settingswindow.grab_set()


        def close_windows(self):
            self.settingswindow.release_set()
            self.settingswindow.destroy()

        SettingsFrame = Frame(self.settingswindow, bg="yellow")
        SettingsFrame.pack(fill=tk.BOTH, side=TOP, expand=True)
        
        SettingsTab = ttk.Notebook(SettingsTabFrame)
        
        PreferencesTab = ttk.Frame(SettingsTab)
        SettingsTab.add(PreferencesTab, text='Preferences')

        AppearanceTab = ttk.Frame(SettingsTab)
        SettingsTab.add(AppearanceTab, text='Appearance')

        InfoTab = ttk.Frame(SettingsTab)
        SettingsTab.add(InfoTab, text='Info')



def main():
    mainwindow = tk.Tk()
    app = Class1(mainwindow)
    mainwindow.mainloop()


if __name__ == '__main__':
    main()

I don't know what to add to the OpenInfo command to open not only the SettingsGUI, but a specific tab (the third, the InfoTab) of the SettingsGUI.
I'm aware of the select function from ttk Notebook, but I really don't know how to use it from a class to another.

--------------------------- EDIT: ---------------------------

I have two classes in one file, one for the main gui and the other for the little settings gui.

    import tkinter as tk
    from tkinter import ttk
    
    class AssistantGUI:
        def __init__(self, mainwindow):
            self.mainwindow = mainwindow
            self.mainwindow.title("Assistant")
            self.mainwindow.geometry("550x400")
    
            # -- MenuBar --
            MenuBar = tk.Menu(self.mainwindow)
    
            # FirstMenu
            FirstMenu = tk.Menu(MenuBar, tearoff = False)
            # added this
            MenuBar.add_cascade(label = "Open", menu = FirstMenu)
            FirstMenu.add_command(label = "Settings", command = self.OpenSettings)
            FirstMenu.add_command(label = "Info", command = self.OpenInfo)
        
            self.mainwindow.config(menu=MenuBar)
    
        def OpenSettings(self):
            self.OpenSettings = tk.Toplevel(self.mainwindow)
            self.app = SettingsGUI(self.OpenSettings)

        def OpenInfo(self):
            self.OpenSettings = tk.Toplevel(self.mainwindow)
            self.app = SettingsGUI(self.OpenSettings)
            # -- MISSING CODE HERE TO SELECT INFOTAB --
    
    class SettingsGUI:
        def __init__(self, settingswindow):
            self.settingswindow = settingswindow
            self.settingswindow.title("Settings")
            self.settingswindow.geometry("300x250")
            
            self.settingswindow.grab_set()
    
            def close_windows(self):
                self.settingswindow.destroy()
    
            SettingsFrame = tk.Frame(self.settingswindow, bg = "yellow")
            SettingsFrame.pack(fill = tk.BOTH, side = tk.TOP, expand = True)
            # changed this from SettingsTabFrame
            SettingsTab = ttk.Notebook(SettingsFrame)
            
            PreferencesTab = ttk.Frame(SettingsTab)
            SettingsTab.add(PreferencesTab, text = 'Preferences')
    
            AppearanceTab = ttk.Frame(SettingsTab)
            SettingsTab.add(AppearanceTab, text = 'Appearance')
    
            InfoTab = ttk.Frame(SettingsTab)
            SettingsTab.add(InfoTab, text = 'Info')
    
            # added these
            SettingsTab.pack(fill = tk.BOTH, side = tk.TOP, expand = True)
           
            # Force focus on settingswindow
            SettingsTab.focus_force()
    
    def main():
        mainwindow = tk.Tk()
        app = AssistantGUI(mainwindow)
        mainwindow.mainloop()
    
    if __name__ == '__main__':
        main()

I don't know what to add to the OpenInfo command to open not only the SettingsGUI, but a specific tab (the third, the InfoTab) of the SettingsGUI.
I'm aware of the select function from ttk Notebook, but I really don't know how to use it from a class to another.


Solution

  • I've made a few changes to your code.

    Code has remarks inserted at relevant places that detail all changes.

    The main ones were SettingsTab.select(InfoTab) and 'SettingsTab.pack(...`

    Also your menu needed to tweak with add_cascade.

    import tkinter as tk
    from tkinter import ttk
    
    # changed this from Class1
    class AssistantGUI:
        def __init__(self, mainwindow):
            self.mainwindow = mainwindow
            self.mainwindow.title("Assistant")
            self.mainwindow.geometry("550x400")
    
            # -- MenuBar --
            MenuBar = tk.Menu(self.mainwindow)
    
            # FirstMenu
            FirstMenu = tk.Menu(MenuBar, tearoff = False)
            # added this
            MenuBar.add_cascade(label = "Open", menu = FirstMenu)
            FirstMenu.add_command(label = "Settings", command = self.OpenInfo)
        
            self.mainwindow.config(menu=MenuBar)
    
        def OpenInfo(self):
            self.OpenSettings = tk.Toplevel(self.mainwindow)
            self.app = SettingsGUI(self.OpenSettings)
    
            # -- MISSING CODE HERE --
    
    class SettingsGUI:
        def __init__(self, settingswindow):
            self.settingswindow = settingswindow
            self.settingswindow.title("Settings")
            self.settingswindow.geometry("300x250")
            
            self.settingswindow.grab_set()
    
            def close_windows(self):
                # removed grab_release
                self.settingswindow.destroy()
    
            SettingsFrame = tk.Frame(self.settingswindow, bg = "yellow")
            SettingsFrame.pack(fill = tk.BOTH, side = tk.TOP, expand = True)
            # changed this from SettingsTabFrame
            SettingsTab = ttk.Notebook(SettingsFrame)
            
            PreferencesTab = ttk.Frame(SettingsTab)
            SettingsTab.add(PreferencesTab, text = 'Preferences')
    
            AppearanceTab = ttk.Frame(SettingsTab)
            SettingsTab.add(AppearanceTab, text = 'Appearance')
    
            InfoTab = ttk.Frame(SettingsTab)
            SettingsTab.add(InfoTab, text = 'Info')
    
            # added these
            SettingsTab.pack(fill = tk.BOTH, side = tk.TOP, expand = True)
            # focus on InfoTab
            SettingsTab.select(InfoTab)
            # Force focus on settingswindow
            SettingsTab.focus_force()
    
    def main():
        mainwindow = tk.Tk()
        app = AssistantGUI(mainwindow)
        mainwindow.mainloop()
    
    if __name__ == '__main__':
        main()
    

    If you want to keep control in OpenInfo then change it like this.

        def OpenInfo(self):
            self.OpenSettings = tk.Toplevel(self.mainwindow)
            self.app = SettingsGUI(self.OpenSettings)
            # focus on InfoTab
            self.app.SettingsTab.select(self.app.InfoTab)
            # Force focus on settingswindow
            self.app.SettingsTab.focus_force()
    

    You will have to change SettingsTab and InfoTab by prepending each with 'self.'