schonmal geschrieben.
Code: Alles auswählen
#!/usr/bin/env python
from functools import partial
import string
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
class Listbox(tk.Listbox):
def __init__(self, master, command, cnf={}, **kwargs):
tk.Listbox.__init__(self, master, cnf, **kwargs)
self.config(selectmode="browse")
self.command = command
self._searched = ""
self._letters = True
self.label = None
self.bind("<Key>", self._find)
self.bind("<Return>", self.run_command)
self.bind("<Double-Button-1>", self.run_command)
def _find(self, event):
self.find(event.keysym)
def run_command(self, _event=None):
if self.command:
self.command(self)
def attach(self, items):
input_max = 0
for item in items:
self.insert("end", item)
input_length = len(item)
if input_length > input_max:
input_max = input_length
self.config(width=input_max + 1)
self.selection_set(0)
def get_currentindex(self):
try:
return int(self.curselection()[0])
except IndexError:
return 0
def select(self, index):
old = self.get_currentindex()
self.selection_clear(old)
self.selection_set(index)
self.yview_scroll(index - old if old != 0 else index, "unit")
def jump_to(self, index):
self.select(index)
self.run_command()
def find(self, key):
key = key.lower()
if key == "down":
self._searched = ""
self.jump_to(self.get_currentindex() + 1)
return
elif key == "up":
self._searched = ""
self.jump_to(self.get_currentindex() - 1)
return
elif key in string.digits and self._letters:
self._searched = key
self._letters = False
elif key in string.ascii_lowercase and not self._letters:
self._searched = key
self._letters = True
elif key in string.ascii_lowercase + string.digits:
self._searched += key
elif key == "space":
self._searched += " "
elif key == "backspace":
self._searched = self._searched[:-1]
if self._searched == "":
self.jump_to(0)
if self.label:
self.label.config(text=self._searched.replace(" ", "_"))
for index, row in enumerate(self.get(0, "end")):
if self._letters:
if row.lower().startswith(self._searched):
self.jump_to(index)
return
else:
if row.startswith(self._searched):
self.jump_to(index)
return
class ScrolledListFrame(tk.Frame):
def __init__(self, master, command, cnf={}, **kwargs):
tk.Frame.__init__(self, master, cnf, **kwargs)
self.listbox = Listbox(self, command)
self.listbox.label = tk.Label(self, text="")
self.listbox.label.pack(expand=False, fill="both", side="bottom")
self.listbox.pack(expand=True, fill="both", side="left")
self.vbar = tk.Scrollbar(self)
self.vbar.pack(expand=True, fill="both", side="right")
self.vbar.config(command=self.listbox.yview)
self.listbox.config(yscrollcommand=self.vbar.set)
for widget in [self, self.vbar]:
widget.bind("<MouseWheel>", self._scroll)
widget.bind("<Button-4>", self._scroll)
widget.bind("<Button-5>", self._scroll)
def _scroll(self, event):
if event.num == 5 or event.delta < 0:
self.listbox.yview_scroll(1, "unit")
elif event.num == 4 or event.delta > 0:
self.listbox.yview_scroll(-1, "unit")
class ScrolledListMenu(tk.Button):
def __init__(self, master, cnf={}, **kwargs):
cnf.update({"borderwidth": 2, "relief": "raised", "anchor": "c",
"highlightthickness": 2})
tk.Button.__init__(self, master, cnf, **kwargs)
self.bind("<Button-1>", self.popup)
self.frame = None
self.top = tk.Toplevel(self)
self.top.overrideredirect(True)
self.top.bind("<Leave>", self.hide)
self.hide(None)
def attach(self, content, command):
if self.frame:
self.frame.pack_forget()
self.frame = ScrolledListFrame(self.top, command)
self.frame.listbox.attach(content)
self.frame.pack(expand=True, fill="both")
def popup(self, event):
x, y = self.winfo_rootx(), self.winfo_rooty()
self.top.geometry("+{0}+{1}".format(x, y + self.winfo_reqheight()))
self.top.deiconify()
self.frame.listbox.focus_set()
def hide(self, event):
self.top.withdraw()
def get(menu, font, listbox):
menu.hide(None)
font.set(listbox.get(listbox.get_currentindex()))
if __name__ == "__main__":
content = ["Arial", "Arial Black", "Comic Sans MS", "Courier New",
"DejaVu Sans", "DejaVu Sans Condensed", "DejaVu Sans Light",
"DejaVu Sans Mono", "DejaVu Serif", "DejaVu Serif Condensed",
"Estrangelo Edessa", "Franklin Gothic Medium", "Gautami"]
root = tk.Tk()
font = tk.StringVar()
tk.Label(root, textvariable=font).pack(side="right")
slm = ScrolledListMenu(root, text="Schriftart: ")
slm.attach(content, partial(get, slm, font))
slm.pack(side="left")
root.mainloop()