Changing tab widgets from another tab in Tkinter

I am creating a GUI using tkinter based on the structure described here. I have some tabs that look identical but with different variables. So I decided to define a class for tabs and add them to the main window. I am going to configure some widgets in one tab from another tab. In line 11, a function is defined that when a button in tab_2 is clicked, tab_1‘s button background color changes to green. Whereas its working, I have two question:

  1. Is it possible not to define channel_1 as an attribute of main_window? I think there must be better way to do so, specifically, if the GUI is going to be used as module (then main_window will not be defined).

  2. Is it possible to know which tab is open, so when button in each tab is clicked, configurations in the other one changes only?

import tkinter as tk
from tkinter import ttk

class Channel(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.btn = tk.Button(self.parent, text = 'click me', command = self.change_green)
        self.btn.pack()
    def change_green(self):
        main_window.channel_1.btn.config(bg = 'green') # line 11


class MainApplication(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.tab_control = ttk.Notebook(self.parent)
        self.tab_1 = ttk.Frame(self.tab_control)
        self.tab_2 = ttk.Frame(self.tab_control)
        self.tab_control.add(self.tab_1, text = 'tab 1')
        self.tab_control.add(self.tab_2, text = 'tab 2')
        self.tab_control.pack(fill = 'both', expand = 1)

        self.channel_1 = Channel(self.tab_1)
        self.channel_2 = Channel(self.tab_2)

if __name__ == "__main__":
    root = tk.Tk()
    main_window = MainApplication(root)    # <<<< here defined main_window
    main_window.pack(side="top", fill="both", expand=True)
    root.mainloop()

Answer

I would create class MyTab and keep its widgets in this class, not in channel. It can also keep access to other tab(s) to button in one tab can change color in other tab.

Using tab’s parent (self.master) I can get active tab, list of all tabs and activate other tab.

import tkinter as tk
from tkinter import ttk


class MyTab(tk.Frame):

    def __init__(self, master, *args, **kwargs):
        super().__init__(master, *args, **kwargs)
        #self.master = master #  super() already set it

        self.btn = tk.Button(self, text='click me', command=self.change_green)
        self.btn.pack()

        self.other_tab = None # default value at start

    def change_green(self):
        if self.other_tab:

            # change color in other tab
            self.other_tab.btn.config(bg = 'green')

            # get active tab ID
            print('active tab ID:', self.master.select())

            # get button in active tab
            active_tab = root.nametowidget(self.master.select())
            print('active tab - btn text:', active_tab.btn['text'])

            # get all tabs
            print('all tabs:', self.master.children.items())

            # set other tab as active
            self.master.select(self.other_tab)

class MainApplication(tk.Frame):

    def __init__(self, master, *args, **kwargs):
        super().__init__(master, *args, **kwargs)
        #self.master = master #  super() already set it

        self.tab_control = ttk.Notebook(self.master)

        self.tab_1 = MyTab(self.tab_control)
        self.tab_2 = MyTab(self.tab_control)

        self.tab_1.other_tab = self.tab_2
        self.tab_2.other_tab = self.tab_1

        self.tab_control.add(self.tab_1, text = 'tab 1')
        self.tab_control.add(self.tab_2, text = 'tab 2')
        self.tab_control.pack(fill = 'both', expand = 1)

if __name__ == "__main__":
    root = tk.Tk()
    main_window = MainApplication(root)
    main_window.pack(side="top", fill="both", expand=True)
    root.mainloop()

Leave a Reply

Your email address will not be published. Required fields are marked *