| from Tkinter import * |
| |
| class ScrolledList: |
| |
| def __init__(self, master, **options): |
| # Create top frame, with scrollbar and listbox |
| self.master = master |
| self.frame = frame = Frame(master) |
| self.frame.pack(fill="both", expand=1) |
| self.vbar = vbar = Scrollbar(frame, name="vbar") |
| self.vbar.pack(side="right", fill="y") |
| self.listbox = listbox = Listbox(frame, exportselection=0) |
| if options: |
| listbox.configure(options) |
| listbox.pack(expand=1, fill="both") |
| # Tie listbox and scrollbar together |
| vbar["command"] = listbox.yview |
| listbox["yscrollcommand"] = vbar.set |
| # Bind events to the list box |
| listbox.bind("<ButtonRelease-1>", self.click_event) |
| listbox.bind("<Double-ButtonRelease-1>", self.double_click_event) |
| listbox.bind("<ButtonPress-3>", self.popup_event) |
| listbox.bind("<Key-Up>", self.up_event) |
| listbox.bind("<Key-Down>", self.down_event) |
| # Set the focus |
| listbox.focus_set() |
| |
| def clear(self): |
| self.listbox.delete(0, "end") |
| |
| def append(self, item): |
| self.listbox.insert("end", str(item)) |
| |
| def get(self, index): |
| return self.listbox.get(index) |
| |
| def click_event(self, event): |
| self.listbox.activate("@%d,%d" % (event.x, event.y)) |
| index = self.listbox.index("active") |
| self.select(index) |
| self.on_select(index) |
| return "break" |
| |
| def double_click_event(self, event): |
| index = self.listbox.index("active") |
| self.select(index) |
| self.on_double(index) |
| return "break" |
| |
| menu = None |
| |
| def popup_event(self, event): |
| if not self.menu: |
| self.make_menu() |
| menu = self.menu |
| self.listbox.activate("@%d,%d" % (event.x, event.y)) |
| index = self.listbox.index("active") |
| self.select(index) |
| menu.tk_popup(event.x_root, event.y_root) |
| |
| def make_menu(self): |
| menu = Menu(self.listbox, tearoff=0) |
| self.menu = menu |
| self.fill_menu() |
| |
| def up_event(self, event): |
| index = self.listbox.index("active") |
| if self.listbox.selection_includes(index): |
| index = index - 1 |
| else: |
| index = self.listbox.size() - 1 |
| if index < 0: |
| self.listbox.bell() |
| else: |
| self.select(index) |
| self.on_select(index) |
| return "break" |
| |
| def down_event(self, event): |
| index = self.listbox.index("active") |
| if self.listbox.selection_includes(index): |
| index = index + 1 |
| else: |
| index = 0 |
| if index >= self.listbox.size(): |
| self.listbox.bell() |
| else: |
| self.select(index) |
| self.on_select(index) |
| return "break" |
| |
| def select(self, index): |
| self.listbox.focus_set() |
| self.listbox.activate(index) |
| self.listbox.selection_clear(0, "end") |
| self.listbox.selection_set(index) |
| self.listbox.see(index) |
| |
| # Methods to override for specific actions |
| |
| def fill_menu(self): |
| pass |
| |
| def on_select(self, index): |
| pass |
| |
| def on_double(self, index): |
| pass |
| |
| |
| def test(): |
| root = Tk() |
| root.protocol("WM_DELETE_WINDOW", root.destroy) |
| class MyScrolledList(ScrolledList): |
| def fill_menu(self): self.menu.add_command(label="pass") |
| def on_select(self, index): print "select", self.get(index) |
| def on_double(self, index): print "double", self.get(index) |
| s = MyScrolledList(root) |
| for i in range(30): |
| s.append("item %02d" % i) |
| return root |
| |
| def main(): |
| root = test() |
| root.mainloop() |
| |
| if __name__ == '__main__': |
| main() |