Mario Camilleri
Mario Camilleri

Reputation: 1567

In tkinter, is it possible to place the same widget into multiple frames?

I have a UI with ttk.Notebook tabs, and would like to display the same widget in multiple tabs. This requires the widget to simultaneously have multiple parent frames, which doesn't seem possible. Is there some other way it can be done?

Upvotes: 1

Views: 2389

Answers (3)

pkanda
pkanda

Reputation: 149

Yes you can, example using two notebook tabs(aba1, aba2)

def widgets_with_icon(self):

    aba=''
    abas = (self.aba1, self.aba2)
    
    for aba in abas:
        self.tkimage3 = PhotoImage(file="images/salvar_100.png")

        self.bt_image_save = tk.Button(aba, image=self.tkimage3, compound=tk.LEFT, bd=0, bg='#A9A9A9', activebackground='#A9A9A9', command=your_command)
        
        self.bt_image_save.image = self.tkimage3 # reference to image not garbage collect
        self.bt_image_save.place(relx=0.01, rely=0.01, relwidth=0.03, relheight=0.04)
        

self.bt_image_save (button with image only) will appear in aba1 and aba2. I hope it can help.

Upvotes: 0

Mario Camilleri
Mario Camilleri

Reputation: 1567

I have since tinkered around with this problem, and have come up with this preliminary (and largely untested) solution to having a widget appear on multiple tabs of a ttk.Notebook.

Although the physical parent of a widget is immutably set when the widget is created, its geometric parent (which controls where it appears) CAN be changed using the .grid() in_ option. So in theory it should be possible to have the widget appear on multiple notebook tabs simply by changing its geometric parent whenever the user changes to a new tab (NotebookTabChanged)

The following code seems to work as advertised, although I haven't really tested it outside the toy code below:

import tkinter as tk
import tkinter.ttk as ttk

class myApp(tk.Tk):

    def __init__(self):

        super().__init__()

        # Create the Notebook and bind the tab-select event 
        self.notebook = ttk.Notebook(self, width=500, height=200)
        self.notebook.grid()
        self.notebook.bind("<<NotebookTabChanged>>", self.select_tab)

        # Create a status bar which displays the name of the currently selected tab 
        self.status = ttk.Label(self)
        self.status.grid(sticky='w')

        # Create three frames - one for each of three tabs - and store them in 
        # a dictionary with the tab names as keys
        self.tabs = dict()
        self.tabs['PAGE 1'] = ttk.Frame(self.notebook)
        self.tabs['PAGE 2'] = ttk.Frame(self.notebook)
        self.tabs['PAGE 3'] = ttk.Frame(self.notebook)

        # Create the tabs in the notebook
        for t in self.tabs.keys():
            self.notebook.add(self.tabs[t], text=t, underline=0, sticky='nsew')

        # Put a widget on the middle tab, just to have soemthing there
        ttk.Label(self.tabs['PAGE 2'],text="A SIMPLE LABEL").grid(row=0,column=0)
    
        # Create a button - this is the widget we wish to appear on all tabs
        self.btn = tk.Button(self,text='PRESS ME!',command=self.button_pressed)


    # This is the method called when the user selectes a new tab. It 
    # updates the status bar and moves the button to the new tab.
    
    def select_tab(self, event):
        id = self.notebook.select()
        name = self.notebook.tab(id, "text")
        text = f"--- {name} is currently selected ---"
        self.status.config(text=text)
        self.btn.grid(row=4,column=0,in_= self.tabs[name])


    def button_pressed(self):
        print('BUTTON PRESSED')


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

Upvotes: 1

Bryan Oakley
Bryan Oakley

Reputation: 386315

No, you cannot have a single widget in multiple places. A widget can only be in one place at a time.

Upvotes: 1

Related Questions