|
1 """ |
|
2 a couple of classes for implementing partial tabbed-page like behaviour |
|
3 """ |
|
4 |
|
5 from Tkinter import * |
|
6 |
|
7 class InvalidTabPage(Exception): pass |
|
8 class AlreadyExists(Exception): pass |
|
9 |
|
10 class PageTab(Frame): |
|
11 """ |
|
12 a 'page tab' like framed button |
|
13 """ |
|
14 def __init__(self,parent): |
|
15 Frame.__init__(self, parent,borderwidth=2,relief=RIDGE) |
|
16 self.button=Radiobutton(self,padx=5,pady=5,takefocus=FALSE, |
|
17 indicatoron=FALSE,highlightthickness=0, |
|
18 borderwidth=0,selectcolor=self.cget('bg')) |
|
19 self.button.pack() |
|
20 |
|
21 class TabPageSet(Frame): |
|
22 """ |
|
23 a set of 'pages' with TabButtons for controlling their display |
|
24 """ |
|
25 def __init__(self,parent,pageNames=[],**kw): |
|
26 """ |
|
27 pageNames - a list of strings, each string will be the dictionary key |
|
28 to a page's data, and the name displayed on the page's tab. Should be |
|
29 specified in desired page order. The first page will be the default |
|
30 and first active page. |
|
31 """ |
|
32 Frame.__init__(self, parent, kw) |
|
33 self.grid_location(0,0) |
|
34 self.columnconfigure(0,weight=1) |
|
35 self.rowconfigure(1,weight=1) |
|
36 self.tabBar=Frame(self) |
|
37 self.tabBar.grid(row=0,column=0,sticky=EW) |
|
38 self.activePage=StringVar(self) |
|
39 self.defaultPage='' |
|
40 self.pages={} |
|
41 for name in pageNames: |
|
42 self.AddPage(name) |
|
43 |
|
44 def ChangePage(self,pageName=None): |
|
45 if pageName: |
|
46 if pageName in self.pages.keys(): |
|
47 self.activePage.set(pageName) |
|
48 else: |
|
49 raise InvalidTabPage, 'Invalid TabPage Name' |
|
50 ## pop up the active 'tab' only |
|
51 for page in self.pages.keys(): |
|
52 self.pages[page]['tab'].config(relief=RIDGE) |
|
53 self.pages[self.GetActivePage()]['tab'].config(relief=RAISED) |
|
54 ## switch page |
|
55 self.pages[self.GetActivePage()]['page'].lift() |
|
56 |
|
57 def GetActivePage(self): |
|
58 return self.activePage.get() |
|
59 |
|
60 def AddPage(self,pageName): |
|
61 if pageName in self.pages.keys(): |
|
62 raise AlreadyExists, 'TabPage Name Already Exists' |
|
63 self.pages[pageName]={'tab':PageTab(self.tabBar), |
|
64 'page':Frame(self,borderwidth=2,relief=RAISED)} |
|
65 self.pages[pageName]['tab'].button.config(text=pageName, |
|
66 command=self.ChangePage,variable=self.activePage, |
|
67 value=pageName) |
|
68 self.pages[pageName]['tab'].pack(side=LEFT) |
|
69 self.pages[pageName]['page'].grid(row=1,column=0,sticky=NSEW) |
|
70 if len(self.pages)==1: # adding first page |
|
71 self.defaultPage=pageName |
|
72 self.activePage.set(self.defaultPage) |
|
73 self.ChangePage() |
|
74 |
|
75 def RemovePage(self,pageName): |
|
76 if not pageName in self.pages.keys(): |
|
77 raise InvalidTabPage, 'Invalid TabPage Name' |
|
78 self.pages[pageName]['tab'].pack_forget() |
|
79 self.pages[pageName]['page'].grid_forget() |
|
80 self.pages[pageName]['tab'].destroy() |
|
81 self.pages[pageName]['page'].destroy() |
|
82 del(self.pages[pageName]) |
|
83 # handle removing last remaining, or default, or active page |
|
84 if not self.pages: # removed last remaining page |
|
85 self.defaultPage='' |
|
86 return |
|
87 if pageName==self.defaultPage: # set a new default page |
|
88 self.defaultPage=\ |
|
89 self.tabBar.winfo_children()[0].button.cget('text') |
|
90 if pageName==self.GetActivePage(): # set a new active page |
|
91 self.activePage.set(self.defaultPage) |
|
92 self.ChangePage() |
|
93 |
|
94 if __name__ == '__main__': |
|
95 #test dialog |
|
96 root=Tk() |
|
97 tabPage=TabPageSet(root,pageNames=['Foobar','Baz']) |
|
98 tabPage.pack(expand=TRUE,fill=BOTH) |
|
99 Label(tabPage.pages['Foobar']['page'],text='Foo',pady=20).pack() |
|
100 Label(tabPage.pages['Foobar']['page'],text='Bar',pady=20).pack() |
|
101 Label(tabPage.pages['Baz']['page'],text='Baz').pack() |
|
102 entryPgName=Entry(root) |
|
103 buttonAdd=Button(root,text='Add Page', |
|
104 command=lambda:tabPage.AddPage(entryPgName.get())) |
|
105 buttonRemove=Button(root,text='Remove Page', |
|
106 command=lambda:tabPage.RemovePage(entryPgName.get())) |
|
107 labelPgName=Label(root,text='name of page to add/remove:') |
|
108 buttonAdd.pack(padx=5,pady=5) |
|
109 buttonRemove.pack(padx=5,pady=5) |
|
110 labelPgName.pack(padx=5) |
|
111 entryPgName.pack(padx=5) |
|
112 tabPage.ChangePage() |
|
113 root.mainloop() |