简体   繁体   English

使用 ttk.widgets.autocomplete 同时按下两个键时避免自动完成

[英]Avoid autocompleting when two keys are pressed at once with ttk.widgets.autocomplete

I'm trying to create a form using ttk.widgets library.我正在尝试使用 ttk.widgets 库创建一个表单。 When using AutocompleteEntry, I noticed that if I don't press only one key at a time the entry is autocompleted with the first match from the first two keys I pressed (when I release the keys it autocompletes by itself), and so when typing fast this issue occurs.使用 AutocompleteEntry 时,我注意到如果我一次不只按一个键,则条目会自动完成我按下的前两个键的第一个匹配项(当我释放键时它会自行自动完成),因此在键入时快出现这个问题。

import tkinter as tk
from ttkwidgets.autocomplete import AutocompleteEntry


class DfeForm(tk.Tk):

    @staticmethod
    def only_numbers(char):
        return char.isdigit()

    def character_limit(self, entry_text):
        if len(entry_text.get()) > 0:
            entry_text.set(entry_text.get()[:14])

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        padding = {'padx': 5, 'pady': 5}

        self.geometry('340x255')
        self.title("My form")
        validation = self.register(self.only_numbers)

        input1_text = tk.StringVar()
        input1_label = tk.Label(text='Entry to autocomplete:')
        input1_label.grid(row=1, column=0, sticky=tk.E, **padding)
        input1_entry = AutocompleteEntry(self, foreground='black', validate='key',
                                         validatecommand=(validation, '%S'), textvariable=input1_text,
                                         completevalues=autocompleteList)
        input1_entry.grid(row=1, column=1, **padding, sticky=tk.E)
        input1_text.trace("w", lambda *args: self.character_limit(input1_text))
        self.resizable(0, 0)


def main():
    gui = DfeForm()
    gui.mainloop()


autocompleteList = ['123555', '123666', '123777', '223555']

if __name__ == "__main__":
    main()

In this code sample, if you press '1' and then '2' (before releasing '1' key), when you release both keys the text is automatically autocompleted to the first match '123555'.在此代码示例中,如果您按“1”然后按“2”(在释放“1”键之前),当您释放两个键时,文本将自动自动完成到第一个匹配项“123555”。 So, if you try to type '123666' fast, the entry is mistakenly autocompleted to '123555'.因此,如果您尝试快速键入“123666”,该条目会错误地自动完成为“123555”。

ttkwidgets autocomplete is done by '<KeyRelease>' and not by '<KeyPress>' . ttkwidgets 自动完成由'<KeyRelease>'而不是'<KeyPress>'完成。 I guess the intention for this is because on some platforms the key-press event is fired continuously till release (eg Windows).我想这样做的目的是因为在某些平台上,按键事件会持续触发直到发布(例如 Windows)。 This would lead to false results.这会导致错误的结果。 However you could try entry.bind('<KeyPress>', entry.handle_keyrelease)但是你可以尝试entry.bind('<KeyPress>', entry.handle_keyrelease)

You also could implement your own validation for this event and have barrier of time that needs to be bridged to insert the exact same key.您还可以为此事件实施自己的验证,并且有时间障碍需要桥接以插入完全相同的密钥。 It could look like this:它可能看起来像这样:

class MyAutocompleteEntry(AutocompleteEntry):

    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)
        self.last_eval = None
        self.min_delta = 50
        self.bind('<KeyPress>', self.handle_keypress)
        self.unbind('<KeyRelease>')

    def handle_keypress(self, event):
        if self.last_eval:
            if self.last_eval[0] == event.keysym:
                if event.time-self.last_eval[1] > self.min_delta:
                    self.handle_keyrelease(event)
                else:
                    return
            else:
                self.handle_keyrelease(event)
        else:
            self.handle_keyrelease(event)
        self.last_eval = (event.keysym, event.time)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM