Combobox с подсказкой вариантов в tkinter со списком на русском языке
Есть код, который выполняет поиск в списке по нажатию кнопки выпадающего списка (с подсказкой).
И он работает, но если заменить данные списка lst на любые слова на русском языке, например lst=['Австралия', 'Австрия', 'Масао', 'Макао']
, то подсказки перестают выдаваться.
Вопрос следующий: Можно ли вводя текст в окне на русском языке получать подсказки в Combobox для выбора?
from tkinter import *
from ttkwidgets.autocomplete import AutocompleteCombobox # pip install ttkwidgets
lst = ['C', 'C++', 'Java', 'Python', 'Perl', 'PHP', 'ASP', 'JS']
# lst = ['Австралия', 'Австрия', 'Масао', 'Макао']
root = Tk()
# creating Combobox
combo_box = AutocompleteCombobox(root, width=30, completevalues=lst)
combo_box.pack()
root.mainloop()
Ответы (2 шт):
У меня получился только альтернативный вариант и довольно громоздкий:
from tkinter import *
from tkinter import ttk
class AutocompleteCombobox(ttk.Combobox):
def set_completion_list(self, completion_list):
self._completion_list = sorted(completion_list)
self._hits = []
self._hit_index = 0
self.position = 0
self.bind('<KeyRelease>', self.handle_keyrelease)
self['values'] = self._completion_list
def autocomplete(self, delta=0):
if delta:
self.delete(self.position, END)
else:
self.position = len(self.get())
_hits = []
for item in self._completion_list:
if item.lower().startswith(self.get().lower()):
_hits.append(item)
if _hits != self._hits:
self._hit_index = 0
self._hits = _hits
if _hits:
self._hit_index = (self._hit_index + delta) % len(_hits)
self.delete(0, END)
self.insert(0, _hits[self._hit_index])
self.select_range(self.position, END)
def handle_keyrelease(self, event):
if event.keysym in ('BackSpace', 'Left', 'Right', 'Up', 'Down'):
return
if event.keysym == 'Return':
self.autocomplete(1)
else:
self.autocomplete()
root = Tk()
lst = ['Австралия', 'Австрия', 'Масао', 'Макао', 'Germany']
combo_box = AutocompleteCombobox(root, width=30)
combo_box.set_completion_list(lst)
combo_box.pack()
root.mainloop()
Открыв оригинальный код класса AutocompleteCombobox
, удалось локализовать проблему, она находится в методе:
def handle_keyrelease(self, event):
"""
Event handler for the keyrelease event on this widget.
:param event: Tkinter event
"""
if event.keysym == "BackSpace":
self.delete(self.index(tk.INSERT), tk.END)
self.position = self.index(tk.END)
if event.keysym == "Left":
if self.position < self.index(tk.END): # delete the selection
self.delete(self.position, tk.END)
else:
self.position -= 1 # delete one character
self.delete(self.position, tk.END)
if event.keysym == "Right":
self.position = self.index(tk.END) # go to end (no selection)
if event.keysym == "Return":
self.handle_return(None)
return
if len(event.keysym) == 1:
self.autocomplete()
# No need for up/down, we'll jump to the popup
# list at the position of the autocompletion
Проблема в этой строчке - if len(event.keysym) == 1:
Пример:
г -> len(event.keysym) = 2
g -> len(event.keysym) = 1
Кириллические символы проверку не проходят и автозаполнение не срабатывает.
Для решения проблемы предлагаю переписать оригинальный метод, подправив проверки:
import tkinter as tk
from ttkwidgets.autocomplete import AutocompleteCombobox
class CastomAutocompleteCombobox(AutocompleteCombobox):
def handle_keyrelease(self, event):
if event.keysym == "BackSpace":
self.delete(self.index(tk.INSERT), tk.END)
self.position = self.index(tk.END)
elif event.keysym == "Left":
if self.position < self.index(tk.END):
self.delete(self.position, tk.END)
else:
self.position -= 1
self.delete(self.position, tk.END)
elif event.keysym == "Right":
self.position = self.index(tk.END)
elif event.keysym == "Return":
self.handle_return(event)
return
else:
# Вызов автозаполнения для всех других клавиш \ можно дополнить своим условием
self.autocomplete()
root = tk.Tk()
lst = ['Австралия', 'Австрия', 'Макао', 'Масао', 'Java', 'Python', 'Perl', 'PHP']
combo = CastomAutocompleteCombobox(root, completevalues=lst, width=30)
combo.pack(pady=10)
root.mainloop()