Search code examples
python-2.7fileclasstkintermacos-sierra

Adding notebook tabs in tkinter - how do I do it with a class-based structure? (Python 2)


I want each tab to come from it's own class (classes are in their own files - I am just testing the first one for now).

Here is what I tried:

tab1.py

from Tkinter import *
import Tkinter as tk

class Tab(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        fr = Frame(self).pack()
        Label(fr, text="one", bg='red', bd=2).pack()
        Label(fr, text="two", bg='yellow', bd=2).pack()

if __name__ == '__main__':
    root = Tk()
    frame = Frame(root).pack()
    Tab(frame)
    Button(frame, text='only if class', command=root.destroy).pack()
    mainloop()

noteBook.py

from Tkinter import *
from ttk import *
from tab1 import Tab

root = Tk()
note = Notebook(root)

main_frame = Frame(note)
button1 = Button(main_frame, text='test').pack()

#tab1 = Tab(note)
tab1 = Frame(note)
tab2 = Frame(note)
tab3 = Frame(note)
Tab(tab1)
Button(tab1, text='Exit', command=root.destroy).pack()

note.add(tab1, text = "Tab One", compound=TOP)
note.add(tab2, text = "Tab Two")
note.add(tab3, text = "Tab Three")
note.pack()
root.mainloop()
exit()

run with:

python2.7 noteBook.py

The problem is that the content of tab1.py does not appear within the first tab, it instead appears within the frame that contains the whole noteBook.

Also when running tab1.py directly with python2.7 noteBook.py I need it to behave properly meaning from what it has now it should show just the tab with an extra button from the if __name___... part.

I have come accros multiple examples but only found one that was what I want but it had no working solution and it was for python3 - I would like python2. python3 question with no working answer Thanks.


Solution

  • The problem is this line of code:

    fr = Frame(self).pack()
    

    When you do the above, fr is None because .pack() returns None (because x().y() returns the value of y()). Later, you do this:

    Label(fr, text="one", bg='red', bd=2).pack()
    

    Since fr is None, the label is created in the root window.

    Unrelated to the problem, here's some advice: you are creating too many frames. You don't need fr inside of Tab, and you don't need tab1, tab2, or tab3

    Here's all you need for Tab:

    class Tab(tk.Frame):
        def __init__(self, master):
            tk.Frame.__init__(self, master, background="pink")
            Label(self, text="one", bg='red', bd=2).pack()
            Label(self, text="two", bg='yellow', bd=2).pack()
    

    To add it to the notebook, you just need two lines:

    tab1 = Tab(note)
    note.add(tab1, text = "Tab One", compound=TOP)