scrolledlist.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. from tkinter import *
  2. from tkinter.ttk import Frame, Scrollbar
  3. from idlelib import macosx
  4. class ScrolledList:
  5. default = "(None)"
  6. def __init__(self, master, **options):
  7. # Create top frame, with scrollbar and listbox
  8. self.master = master
  9. self.frame = frame = Frame(master)
  10. self.frame.pack(fill="both", expand=1)
  11. self.vbar = vbar = Scrollbar(frame, name="vbar")
  12. self.vbar.pack(side="right", fill="y")
  13. self.listbox = listbox = Listbox(frame, exportselection=0,
  14. background="white")
  15. if options:
  16. listbox.configure(options)
  17. listbox.pack(expand=1, fill="both")
  18. # Tie listbox and scrollbar together
  19. vbar["command"] = listbox.yview
  20. listbox["yscrollcommand"] = vbar.set
  21. # Bind events to the list box
  22. listbox.bind("<ButtonRelease-1>", self.click_event)
  23. listbox.bind("<Double-ButtonRelease-1>", self.double_click_event)
  24. if macosx.isAquaTk():
  25. listbox.bind("<ButtonPress-2>", self.popup_event)
  26. listbox.bind("<Control-Button-1>", self.popup_event)
  27. else:
  28. listbox.bind("<ButtonPress-3>", self.popup_event)
  29. listbox.bind("<Key-Up>", self.up_event)
  30. listbox.bind("<Key-Down>", self.down_event)
  31. # Mark as empty
  32. self.clear()
  33. def close(self):
  34. self.frame.destroy()
  35. def clear(self):
  36. self.listbox.delete(0, "end")
  37. self.empty = 1
  38. self.listbox.insert("end", self.default)
  39. def append(self, item):
  40. if self.empty:
  41. self.listbox.delete(0, "end")
  42. self.empty = 0
  43. self.listbox.insert("end", str(item))
  44. def get(self, index):
  45. return self.listbox.get(index)
  46. def click_event(self, event):
  47. self.listbox.activate("@%d,%d" % (event.x, event.y))
  48. index = self.listbox.index("active")
  49. self.select(index)
  50. self.on_select(index)
  51. return "break"
  52. def double_click_event(self, event):
  53. index = self.listbox.index("active")
  54. self.select(index)
  55. self.on_double(index)
  56. return "break"
  57. menu = None
  58. def popup_event(self, event):
  59. if not self.menu:
  60. self.make_menu()
  61. menu = self.menu
  62. self.listbox.activate("@%d,%d" % (event.x, event.y))
  63. index = self.listbox.index("active")
  64. self.select(index)
  65. menu.tk_popup(event.x_root, event.y_root)
  66. return "break"
  67. def make_menu(self):
  68. menu = Menu(self.listbox, tearoff=0)
  69. self.menu = menu
  70. self.fill_menu()
  71. def up_event(self, event):
  72. index = self.listbox.index("active")
  73. if self.listbox.selection_includes(index):
  74. index = index - 1
  75. else:
  76. index = self.listbox.size() - 1
  77. if index < 0:
  78. self.listbox.bell()
  79. else:
  80. self.select(index)
  81. self.on_select(index)
  82. return "break"
  83. def down_event(self, event):
  84. index = self.listbox.index("active")
  85. if self.listbox.selection_includes(index):
  86. index = index + 1
  87. else:
  88. index = 0
  89. if index >= self.listbox.size():
  90. self.listbox.bell()
  91. else:
  92. self.select(index)
  93. self.on_select(index)
  94. return "break"
  95. def select(self, index):
  96. self.listbox.focus_set()
  97. self.listbox.activate(index)
  98. self.listbox.selection_clear(0, "end")
  99. self.listbox.selection_set(index)
  100. self.listbox.see(index)
  101. # Methods to override for specific actions
  102. def fill_menu(self):
  103. pass
  104. def on_select(self, index):
  105. pass
  106. def on_double(self, index):
  107. pass
  108. def _scrolled_list(parent): # htest #
  109. top = Toplevel(parent)
  110. x, y = map(int, parent.geometry().split('+')[1:])
  111. top.geometry("+%d+%d" % (x+200, y + 175))
  112. class MyScrolledList(ScrolledList):
  113. def fill_menu(self): self.menu.add_command(label="right click")
  114. def on_select(self, index): print("select", self.get(index))
  115. def on_double(self, index): print("double", self.get(index))
  116. scrolled_list = MyScrolledList(top)
  117. for i in range(30):
  118. scrolled_list.append("Item %02d" % i)
  119. if __name__ == '__main__':
  120. from unittest import main
  121. main('idlelib.idle_test.test_scrolledlist', verbosity=2,)
  122. from idlelib.idle_test.htest import run
  123. run(_scrolled_list)