# One or more ScrolledLists with HSeparators between them. # There is a hierarchical relationship between them: # the right list displays the substructure of the selected item # in the left list. import string from Tkinter import * from WindowList import ListedToplevel from Separator import HSeparator from ScrolledList import ScrolledList class MultiScrolledLists: def __init__(self, root, nlists=2): assert nlists >= 1 self.root = root self.nlists = nlists self.path = [] # create top self.top = top = ListedToplevel(root) top.protocol("WM_DELETE_WINDOW", self.close) top.bind("", self.close) self.settitle() # create frames and separators in between self.frames = [] self.separators = [] last = top for i in range(nlists-1): sepa = HSeparator(last) self.separators.append(sepa) frame, last = sepa.parts() self.frames.append(frame) self.frames.append(last) # create labels and lists self.labels = [] self.lists = [] for i in range(nlists): frame = self.frames[i] label = Label(frame, text=self.subtitle(i), relief="groove", borderwidth=2) label.pack(fill="x") self.labels.append(label) list = ScrolledList(frame, width=self.width(i), height=self.height(i)) self.lists.append(list) list.on_select = \ lambda index, i=i, self=self: self.on_select(index, i) list.on_double = \ lambda index, i=i, self=self: self.on_double(index, i) # fill leftmost list (rest get filled on demand) self.fill(0) # XXX one after_idle isn't enough; two are... top.after_idle(self.call_pack_propagate_1) def call_pack_propagate_1(self): self.top.after_idle(self.call_pack_propagate) def call_pack_propagate(self): for frame in self.frames: frame.pack_propagate(0) def close(self, event=None): self.top.destroy() def settitle(self): short = self.shorttitle() long = self.longtitle() if short and long: title = short + " - " + long elif short: title = short elif long: title = long else: title = "Untitled" icon = short or long or title self.top.wm_title(title) self.top.wm_iconname(icon) def longtitle(self): # override this return "Multi Scrolled Lists" def shorttitle(self): # override this return None def width(self, i): # override this return 20 def height(self, i): # override this return 10 def subtitle(self, i): # override this return "Column %d" % i def fill(self, i): for k in range(i, self.nlists): self.lists[k].clear() self.labels[k].configure(text=self.subtitle(k)) list = self.lists[i] l = self.items(i) for s in l: list.append(s) def on_select(self, index, i): item = self.lists[i].get(index) del self.path[i:] self.path.append(item) if i+1 < self.nlists: self.fill(i+1) def items(self, i): # override this l = [] for k in range(10): s = str(k) if i > 0: s = self.path[i-1] + "." + s l.append(s) return l def on_double(self, index, i): pass def main(): root = Tk() quit = Button(root, text="Exit", command=root.destroy) quit.pack() MultiScrolledLists(root, 4) root.mainloop() if __name__ == "__main__": main()