I provide an alternative listbox for tkinter.
Using this trick you can add horizontal and vertical padding to every item and also a width.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | try:
from Tkinter import Label, Frame, Toplevel, Entry
from Tkconstants import *
from ttk import Separator
except ImportError:
from tkinter import Label, Frame, Toplevel, Entry
from tkinter.constants import *
from tkinter.ttk import Separator
try:
basestring
except NameError:
basestring = str
class Listbox(Frame):
def __init__(self, master, options, width=20, bordercolor="#cccccc", foreground="black", background="white", activebackground="#2780E3", activeforeground="white",padx=15, pady=7, command=None):
Frame.__init__(self, master, background=background, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=1, bd= 0)
self._foreground = foreground
self._background = background
self._activebackground = activebackground
self._activeforeground = activeforeground
self._items = []
index = 0
for option in options:
if option is None:
Separator(self, orient=HORIZONTAL).pack(fill=X)
continue
if isinstance(option, basestring):
test = option
value = option
else:
text, value = option
label_item = Label(self, width=width, text=text, background=background, foreground="black", anchor=W, padx=padx, pady=pady)
label_item.pack(fill=X)
label_item.index = index
label_item.value = value
label_item.bind("<Enter>", self._on_enter_label_item)
label_item.bind("<Leave>", self._on_leave_label_item)
label_item.bind("<1>", lambda event, index=index:self._on_click_item(event.widget, index))
self._items.append(label_item)
index += 1
self._actived_item = None
self._command = command
self.bind("<Up>", self._on_up)
self.bind("<Down>", self._on_down)
self.bind("<Return>", self._on_return)
def _on_return(self, event):
if self._command is not None:
if self._actived_item is not None:
self._command(self._actived_item.value)
def _activate_colors(self, label_item):
label_item.configure(background=self._activebackground, foreground=self._activeforeground)
def _deactivate_colors(self, label_item):
label_item.configure(background=self._background, foreground=self._foreground)
def _on_enter_label_item(self, event):
label_item = event.widget
self._activate_colors(label_item)
self._actived_item = label_item
def _on_leave_label_item(self, event):
label_item = event.widget
self._deactivate_colors(label_item)
def _on_click_item(self, label_item, index):
if self._actived_item != label_item:
self._deactivate_colors(self._actived_item)
self._activate_colors(label_item)
self._actived_item = label_item
self.focus_set()
if self._command is not None:
self._command(label_item.value)
def _on_up(self, event):
if self._actived_item is None:
label_item = self._items[0]
self._actived_item = label_item
self._activate_colors(label_item)
else:
index = self._actived_item.index
if index == 0: return
index -= 1
self._deactivate_colors(self._actived_item)
self._actived_item = self._items[index]
self._activate_colors(self._actived_item)
def _on_down(self, event):
if self._actived_item is None:
label_item = self._items[0]
self._actived_item = label_item
self._activate_colors(label_item)
else:
index = self._actived_item.index
if index == len(self._items) - 1: return
index += 1
self._deactivate_colors(self._actived_item)
self._actived_item = self._items[index]
self._activate_colors(self._actived_item)
if __name__ == "__main__":
try:
from Tkinter import Tk
except ImportError:
from tkinter import Tk
root = Tk()
def command(value):
print("selected value: %s"%value)
listbox = Listbox(root, options=(("Spain", "es"), None, ("USA", "us"), ("France","fr"), ("Britain", "br")), command=command)
listbox.pack()
listbox.focus()
root.mainloop()
|