a couple of classes for implementing partial tabbed-page like behaviour
class InvalidTabPage(Exception): pass
class AlreadyExists(Exception): pass
a 'page tab' like framed button
def __init__(self
,parent
):
Frame
.__init
__(self
, parent
,borderwidth
=2,relief
=RIDGE
)
self
.button
=Radiobutton(self
,padx
=5,pady
=5,takefocus
=FALSE
,
indicatoron
=FALSE
,highlightthickness
=0,
borderwidth
=0,selectcolor
=self
.cget('bg'))
a set of 'pages' with TabButtons for controlling their display
def __init__(self
,parent
,pageNames
=[],**kw
):
pageNames - a list of strings, each string will be the dictionary key
to a page's data, and the name displayed on the page's tab. Should be
specified in desired page order. The first page will be the default
Frame
.__init
__(self
, parent
, kw
)
self
.columnconfigure(0,weight
=1)
self
.rowconfigure(1,weight
=1)
self
.tabBar
.grid(row
=0,column
=0,sticky
=EW
)
self
.activePage
=StringVar(self
)
def ChangePage(self
,pageName
=None):
if pageName
in self
.pages
.keys():
self
.activePage
.set(pageName
)
raise InvalidTabPage
, 'Invalid TabPage Name'
## pop up the active 'tab' only
for page
in self
.pages
.keys():
self
.pages
[page
]['tab'].config(relief
=RIDGE
)
self
.pages
[self
.GetActivePage()]['tab'].config(relief
=RAISED
)
self
.pages
[self
.GetActivePage()]['page'].lift()
return self
.activePage
.get()
def AddPage(self
,pageName
):
if pageName
in self
.pages
.keys():
raise AlreadyExists
, 'TabPage Name Already Exists'
self
.pages
[pageName
]={'tab':PageTab(self
.tabBar
),
'page':Frame(self
,borderwidth
=2,relief
=RAISED
)}
self
.pages
[pageName
]['tab'].button
.config(text
=pageName
,
command
=self
.ChangePage
,variable
=self
.activePage
,
self
.pages
[pageName
]['tab'].pack(side
=LEFT
)
self
.pages
[pageName
]['page'].grid(row
=1,column
=0,sticky
=NSEW
)
if len(self
.pages
)==1: # adding first page
self
.defaultPage
=pageName
self
.activePage
.set(self
.defaultPage
)
def RemovePage(self
,pageName
):
if not pageName
in self
.pages
.keys():
raise InvalidTabPage
, 'Invalid TabPage Name'
self
.pages
[pageName
]['tab'].pack_forget()
self
.pages
[pageName
]['page'].grid_forget()
self
.pages
[pageName
]['tab'].destroy()
self
.pages
[pageName
]['page'].destroy()
del(self
.pages
[pageName
])
# handle removing last remaining, or default, or active page
if not self
.pages
: # removed last remaining page
if pageName
==self
.defaultPage
: # set a new default page
self
.tabBar
.winfo_children()[0].button
.cget('text')
if pageName
==self
.GetActivePage(): # set a new active page
self
.activePage
.set(self
.defaultPage
)
if __name__
== '__main__':
tabPage
=TabPageSet(root
,pageNames
=['Foobar','Baz'])
tabPage
.pack(expand
=TRUE
,fill
=BOTH
)
Label(tabPage
.pages
['Foobar']['page'],text
='Foo',pady
=20).pack()
Label(tabPage
.pages
['Foobar']['page'],text
='Bar',pady
=20).pack()
Label(tabPage
.pages
['Baz']['page'],text
='Baz').pack()
buttonAdd
=Button(root
,text
='Add Page',
command
=lambda:tabPage
.AddPage(entryPgName
.get()))
buttonRemove
=Button(root
,text
='Remove Page',
command
=lambda:tabPage
.RemovePage(entryPgName
.get()))
labelPgName
=Label(root
,text
='name of page to add/remove:')
buttonAdd
.pack(padx
=5,pady
=5)
buttonRemove
.pack(padx
=5,pady
=5)