1
+ import tkinter
2
+ import tkinter .ttk
3
+
4
+ tkinter_umlauts = ['odiaeresis' , 'adiaeresis' , 'udiaeresis' , 'Odiaeresis' , 'Adiaeresis' , 'Udiaeresis' , 'ssharp' ]
5
+ class myentry (tkinter .Entry ):
6
+ def set_completion_list (self , completion_list ):
7
+ self ._completion_list = sorted (completion_list , key = str .lower )
8
+ self ._hits = []
9
+ self ._hit_index = 0
10
+ self .position = 0
11
+ self .bind ('<KeyRelease>' , self .handle_keyrelease )
12
+
13
+ def autocomplete (self , delta = 0 ):
14
+ if delta :
15
+ self .delete (self .position , tkinter .END )
16
+ else :
17
+ self .position = len (self .get ())
18
+ _hits = []
19
+ for element in self ._completion_list :
20
+ if element .lower ().startswith (self .get ().lower ()):
21
+ _hits .append (element )
22
+ if _hits != self ._hits :
23
+ self ._hit_index = 0
24
+ self ._hits = _hits
25
+ if _hits == self ._hits and self ._hits :
26
+ self ._hit_index = (self ._hit_index + delta ) % len (self ._hits )
27
+ if self ._hits :
28
+ self .delete (0 ,tkinter .END )
29
+ self .insert (0 ,self ._hits [self ._hit_index ])
30
+ self .select_range (self .position ,tkinter .END )
31
+
32
+ def handle_keyrelease (self , event ):
33
+ if event .keysym == "BackSpace" :
34
+ self .delete (self .index (tkinter .INSERT ), tkinter .END )
35
+ self .position = self .index (tkinter .END )
36
+ if event .keysym == "Left" :
37
+ if self .position < self .index (tkinter .END ):
38
+ self .delete (self .position , tkinter .END )
39
+ else :
40
+ self .position = self .position - 1
41
+ self .delete (self .position , tkinter .END )
42
+ if event .keysym == "Right" :
43
+ self .position = self .index (tkinter .END )
44
+ if event .keysym == "Down" :
45
+ self .autocomplete (1 )
46
+ if event .keysym == "Up" :
47
+ self .autocomplete (- 1 )
48
+ if len (event .keysym ) == 1 or event .keysym in tkinter_umlauts :
49
+ self .autocomplete ()
50
+
51
+ class mycombobox (tkinter .ttk .Combobox ):
52
+
53
+ def set_completion_list (self , completion_list ):
54
+ self ._completion_list = sorted (completion_list , key = str .lower )
55
+ self ._hits = []
56
+ self ._hit_index = 0
57
+ self .position = 0
58
+ self .bind ('<KeyRelease>' , self .handle_keyrelease )
59
+ self ['values' ] = self ._completion_list
60
+
61
+ def autocomplete (self , delta = 0 ):
62
+ if delta :
63
+ self .delete (self .position , tkinter .END )
64
+ else :
65
+ self .position = len (self .get ())
66
+ _hits = []
67
+ for element in self ._completion_list :
68
+ if element .lower ().startswith (self .get ().lower ()): # Match case insensitively
69
+ _hits .append (element )
70
+ if _hits != self ._hits :
71
+ self ._hit_index = 0
72
+ self ._hits = _hits
73
+ if _hits == self ._hits and self ._hits :
74
+ self ._hit_index = (self ._hit_index + delta ) % len (self ._hits )
75
+ if self ._hits :
76
+ self .delete (0 ,tkinter .END )
77
+ self .insert (0 ,self ._hits [self ._hit_index ])
78
+ self .select_range (self .position ,tkinter .END )
79
+
80
+ def handle_keyrelease (self , event ):
81
+ if event .keysym == "BackSpace" :
82
+ self .delete (self .index (tkinter .INSERT ), tkinter .END )
83
+ self .position = self .index (tkinter .END )
84
+ if event .keysym == "Left" :
85
+ if self .position < self .index (tkinter .END ):
86
+ self .delete (self .position , tkinter .END )
87
+ else :
88
+ self .position = self .position - 1
89
+ self .delete (self .position , tkinter .END )
90
+ if event .keysym == "Right" :
91
+ self .position = self .index (tkinter .END )
92
+ if len (event .keysym ) == 1 :
93
+ self .autocomplete ()
94
+ # TEST THIS
95
+ def test (test_list ):
96
+ root = tkinter .Tk (className = ' AutocompleteEntry demo' )
97
+ entry = myentry (root )
98
+ entry .set_completion_list (test_list )
99
+ entry .pack ()
100
+ entry .focus_set ()
101
+ combo = mycombobox (root )
102
+ combo .set_completion_list (test_list )
103
+ combo .pack ()
104
+ combo .focus_set ()
105
+ root .bind ('<Control-Q>' , lambda event = None : root .destroy ())
106
+ root .bind ('<Control-q>' , lambda event = None : root .destroy ())
107
+ root .mainloop ()
0 commit comments