Уточнить функционал автозаполнения Tkinter - PullRequest
0 голосов
/ 17 октября 2019

У меня есть несколько вопросов об этой записи автозаполнения Tkinter от Mitja Martini .

Я удалил несущественный код и оставил комментарии автора. Автозаполнение работает нормально, если вы набираете достаточно медленно, чтобы подсветка выполнялась после каждого символа, но медленный ввод отрицательно сказывается на цели автозаполнения, так как экономится мало времени. Пользователю придется наблюдать за мигающей подсветкой или просто печатать очень медленно, если он не хочет следить за вспышкой.

Почему я не могу набирать быстро, если выделение не выделено и курсор не переместился наконец заполненного слова;В результате быстрый набор добавляет символы к концу завершенного слова.

Как это можно исправить?

Что подразумевается под "новым списком совпадений" (условно закомментировано). Я хотел бы увидеть простой пример того, как это будет работать и / или почему я не могу просто удалить это условие.

Что подразумевается под «известным списком совпадений» (раздел закомментирован). Что является примером неизвестного списка совпадений в этом коде, так что я могу видеть закомментированные строки в работе?

import tkinter as tk

class AutocompleteEntry(tk.Entry):
    def set_completion_list(self, completion_list):
        self._completion_list = completion_list
        self._hits = []
        self._hit_index = 0
        self.position = 0
        self.bind('<KeyRelease>', self.handle_keyrelease)

    def autocomplete(self):

        # set position to end so selection starts where textentry ended
        self.position = len(self.get())

        # collect hits
        _hits = []
        for element in self._completion_list:
            if element.lower().startswith(self.get().lower()):
                _hits.append(element)

        # if we have a new hit list, keep this in mind 
        # if _hits != self._hits:
        self._hit_index = 0
        self._hits =_hits

        # # only allow cycling if we are in a known hit list
        # if _hits == self._hits and self._hits:
            # self._hit_index = (self._hit_index) % len(self._hits)

        # perform the auto completion
        if self._hits:
            self.delete(0,tk.END)
            self.insert(0,self._hits[self._hit_index])
            self.select_range(self.position,tk.END)

    def handle_keyrelease(self, event):
        if len(event.keysym) == 1:
            self.autocomplete()

def test(test_list):
    root = tk.Tk(className=' AutocompleteEntry demo')
    root.geometry('+500+300')
    entry = AutocompleteEntry(
        root, 
        fg='white', bg='black',
        insertbackground='white', 
        font=('arial', 30))
    entry.set_completion_list(test_list)
    entry.grid()
    entry.focus_set()
    root.mainloop()

if __name__ == '__main__':
    test_list = (
        'Geronimo', 'Tecumseh', 'onomatopoeia', 
        'onerous', 'technicality', 'geriatric' )
    test(test_list)

1 Ответ

1 голос
/ 17 октября 2019

Проблема с кодом автозаполнения заключается в том, что он полагается на замену выделенного текста, поэтому пользователю приходится ждать выделения текста, прежде чем вводить следующий символ. После публикации моего вопроса я написал свое собственное автозаполнение с нуля, в котором используется другая техника, которая позволяет пользователю продолжать печатать после того, как слово заполнено. Это не отвечает на вопросы, как указано выше, но решает мою непосредственную проблему, если только этот кодесть глюк я еще не нашел. Цель этого частичного ответа - показать автозаполнение, которое не мешает пользователю печатать после заполнения слова.

import tkinter as tk

chiefs = [
    'Sitting Bull', 'Geronimo', 'Tecumseh', 'Pontiac', 
    'Red Cloud', 'Crazy Horse', 'Cochise', 'Red Jacket', 
    'Red Czar', 'Red Czechoslovakian']

def match_string():
    hits = []
    got = auto.get()
    for item in chiefs:
        if item.startswith(got):
            hits.append(item)
    return hits    

def get_typed(event):
    if len(event.keysym) == 1:
        hits = match_string()
        show_hit(hits)

def show_hit(lst):
    if len(lst) == 1:
        auto.set(lst[0])
        detect_pressed.filled = True

def detect_pressed(event):    
    key = event.keysym
    if len(key) == 1 and detect_pressed.filled is True:
        pos = autofill.index(tk.INSERT)
        autofill.delete(pos, tk.END)

detect_pressed.filled = False

root = tk.Tk()

auto = tk.StringVar()

autofill = tk.Entry(
    root, 
    font=('tacoma', 30),
    bg='black',
    insertbackground='white',
    fg='white',
    textvariable=auto)
autofill.grid()
autofill.focus_set()
autofill.bind('<KeyRelease>', get_typed)
autofill.bind('<Key>', detect_pressed)

root.mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...