Welcome, guest | Sign In | My Account | Store | Cart
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()

Diff to Previous Revision

--- revision 1 2017-04-16 00:35:09
+++ revision 2 2017-04-16 16:48:22
@@ -14,7 +14,7 @@
 
 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, background=background, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=1, bd= 0)
+        Frame.__init__(self, master, background=background, highlightbackground=bordercolor, highlightcolor=bordercolor, highlightthickness=1, bd= 0)
 
         self._foreground = foreground
         self._background = background

History