17db96d56Sopenharmony_cifrom tkinter import * 27db96d56Sopenharmony_cifrom tkinter.ttk import Frame, Scrollbar 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_cifrom idlelib import macosx 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ciclass ScrolledList: 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci default = "(None)" 107db96d56Sopenharmony_ci 117db96d56Sopenharmony_ci def __init__(self, master, **options): 127db96d56Sopenharmony_ci # Create top frame, with scrollbar and listbox 137db96d56Sopenharmony_ci self.master = master 147db96d56Sopenharmony_ci self.frame = frame = Frame(master) 157db96d56Sopenharmony_ci self.frame.pack(fill="both", expand=1) 167db96d56Sopenharmony_ci self.vbar = vbar = Scrollbar(frame, name="vbar") 177db96d56Sopenharmony_ci self.vbar.pack(side="right", fill="y") 187db96d56Sopenharmony_ci self.listbox = listbox = Listbox(frame, exportselection=0, 197db96d56Sopenharmony_ci background="white") 207db96d56Sopenharmony_ci if options: 217db96d56Sopenharmony_ci listbox.configure(options) 227db96d56Sopenharmony_ci listbox.pack(expand=1, fill="both") 237db96d56Sopenharmony_ci # Tie listbox and scrollbar together 247db96d56Sopenharmony_ci vbar["command"] = listbox.yview 257db96d56Sopenharmony_ci listbox["yscrollcommand"] = vbar.set 267db96d56Sopenharmony_ci # Bind events to the list box 277db96d56Sopenharmony_ci listbox.bind("<ButtonRelease-1>", self.click_event) 287db96d56Sopenharmony_ci listbox.bind("<Double-ButtonRelease-1>", self.double_click_event) 297db96d56Sopenharmony_ci if macosx.isAquaTk(): 307db96d56Sopenharmony_ci listbox.bind("<ButtonPress-2>", self.popup_event) 317db96d56Sopenharmony_ci listbox.bind("<Control-Button-1>", self.popup_event) 327db96d56Sopenharmony_ci else: 337db96d56Sopenharmony_ci listbox.bind("<ButtonPress-3>", self.popup_event) 347db96d56Sopenharmony_ci listbox.bind("<Key-Up>", self.up_event) 357db96d56Sopenharmony_ci listbox.bind("<Key-Down>", self.down_event) 367db96d56Sopenharmony_ci # Mark as empty 377db96d56Sopenharmony_ci self.clear() 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci def close(self): 407db96d56Sopenharmony_ci self.frame.destroy() 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ci def clear(self): 437db96d56Sopenharmony_ci self.listbox.delete(0, "end") 447db96d56Sopenharmony_ci self.empty = 1 457db96d56Sopenharmony_ci self.listbox.insert("end", self.default) 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_ci def append(self, item): 487db96d56Sopenharmony_ci if self.empty: 497db96d56Sopenharmony_ci self.listbox.delete(0, "end") 507db96d56Sopenharmony_ci self.empty = 0 517db96d56Sopenharmony_ci self.listbox.insert("end", str(item)) 527db96d56Sopenharmony_ci 537db96d56Sopenharmony_ci def get(self, index): 547db96d56Sopenharmony_ci return self.listbox.get(index) 557db96d56Sopenharmony_ci 567db96d56Sopenharmony_ci def click_event(self, event): 577db96d56Sopenharmony_ci self.listbox.activate("@%d,%d" % (event.x, event.y)) 587db96d56Sopenharmony_ci index = self.listbox.index("active") 597db96d56Sopenharmony_ci self.select(index) 607db96d56Sopenharmony_ci self.on_select(index) 617db96d56Sopenharmony_ci return "break" 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ci def double_click_event(self, event): 647db96d56Sopenharmony_ci index = self.listbox.index("active") 657db96d56Sopenharmony_ci self.select(index) 667db96d56Sopenharmony_ci self.on_double(index) 677db96d56Sopenharmony_ci return "break" 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci menu = None 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci def popup_event(self, event): 727db96d56Sopenharmony_ci if not self.menu: 737db96d56Sopenharmony_ci self.make_menu() 747db96d56Sopenharmony_ci menu = self.menu 757db96d56Sopenharmony_ci self.listbox.activate("@%d,%d" % (event.x, event.y)) 767db96d56Sopenharmony_ci index = self.listbox.index("active") 777db96d56Sopenharmony_ci self.select(index) 787db96d56Sopenharmony_ci menu.tk_popup(event.x_root, event.y_root) 797db96d56Sopenharmony_ci return "break" 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci def make_menu(self): 827db96d56Sopenharmony_ci menu = Menu(self.listbox, tearoff=0) 837db96d56Sopenharmony_ci self.menu = menu 847db96d56Sopenharmony_ci self.fill_menu() 857db96d56Sopenharmony_ci 867db96d56Sopenharmony_ci def up_event(self, event): 877db96d56Sopenharmony_ci index = self.listbox.index("active") 887db96d56Sopenharmony_ci if self.listbox.selection_includes(index): 897db96d56Sopenharmony_ci index = index - 1 907db96d56Sopenharmony_ci else: 917db96d56Sopenharmony_ci index = self.listbox.size() - 1 927db96d56Sopenharmony_ci if index < 0: 937db96d56Sopenharmony_ci self.listbox.bell() 947db96d56Sopenharmony_ci else: 957db96d56Sopenharmony_ci self.select(index) 967db96d56Sopenharmony_ci self.on_select(index) 977db96d56Sopenharmony_ci return "break" 987db96d56Sopenharmony_ci 997db96d56Sopenharmony_ci def down_event(self, event): 1007db96d56Sopenharmony_ci index = self.listbox.index("active") 1017db96d56Sopenharmony_ci if self.listbox.selection_includes(index): 1027db96d56Sopenharmony_ci index = index + 1 1037db96d56Sopenharmony_ci else: 1047db96d56Sopenharmony_ci index = 0 1057db96d56Sopenharmony_ci if index >= self.listbox.size(): 1067db96d56Sopenharmony_ci self.listbox.bell() 1077db96d56Sopenharmony_ci else: 1087db96d56Sopenharmony_ci self.select(index) 1097db96d56Sopenharmony_ci self.on_select(index) 1107db96d56Sopenharmony_ci return "break" 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci def select(self, index): 1137db96d56Sopenharmony_ci self.listbox.focus_set() 1147db96d56Sopenharmony_ci self.listbox.activate(index) 1157db96d56Sopenharmony_ci self.listbox.selection_clear(0, "end") 1167db96d56Sopenharmony_ci self.listbox.selection_set(index) 1177db96d56Sopenharmony_ci self.listbox.see(index) 1187db96d56Sopenharmony_ci 1197db96d56Sopenharmony_ci # Methods to override for specific actions 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ci def fill_menu(self): 1227db96d56Sopenharmony_ci pass 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci def on_select(self, index): 1257db96d56Sopenharmony_ci pass 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci def on_double(self, index): 1287db96d56Sopenharmony_ci pass 1297db96d56Sopenharmony_ci 1307db96d56Sopenharmony_ci 1317db96d56Sopenharmony_cidef _scrolled_list(parent): # htest # 1327db96d56Sopenharmony_ci top = Toplevel(parent) 1337db96d56Sopenharmony_ci x, y = map(int, parent.geometry().split('+')[1:]) 1347db96d56Sopenharmony_ci top.geometry("+%d+%d" % (x+200, y + 175)) 1357db96d56Sopenharmony_ci class MyScrolledList(ScrolledList): 1367db96d56Sopenharmony_ci def fill_menu(self): self.menu.add_command(label="right click") 1377db96d56Sopenharmony_ci def on_select(self, index): print("select", self.get(index)) 1387db96d56Sopenharmony_ci def on_double(self, index): print("double", self.get(index)) 1397db96d56Sopenharmony_ci 1407db96d56Sopenharmony_ci scrolled_list = MyScrolledList(top) 1417db96d56Sopenharmony_ci for i in range(30): 1427db96d56Sopenharmony_ci scrolled_list.append("Item %02d" % i) 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ciif __name__ == '__main__': 1457db96d56Sopenharmony_ci from unittest import main 1467db96d56Sopenharmony_ci main('idlelib.idle_test.test_scrolledlist', verbosity=2,) 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci from idlelib.idle_test.htest import run 1497db96d56Sopenharmony_ci run(_scrolled_list) 150