如何在能够输入的同时将输入限制为仅 AutocompleteCombobox 中的可用选项?

发布于 2025-01-12 12:39:47 字数 207 浏览 1 评论 0原文

我正在使用 ttkwidgets.autocomplete 中的 AutocompleteCombobox 作为我的选择小部件。虽然所有功能都很好(例如能够在键入时过滤列表),但我希望能够键入它,但只能从可用选项中键入,即,我不应该能够键入自定义值。 我尝试使用 state=readonly 但它不允许我在组合框中输入。 任何解决方案将不胜感激。

I am using AutocompleteCombobox from ttkwidgets.autocomplete for my selection widget. While all the features are good (like being able to filter the list while typing), I want to be able to type in it but only from the available options ie., I should not be able to type in custom values.
I tried using state=readonly but it doesn't allow me to type in the combobox.
Any solutions would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

三生池水覆流年 2025-01-19 12:39:47

由于您没有提供示例代码,并且 tkinter 没有提供默认的自动完成组合,我假设您正在使用 ttkwidgets.autocomplete 中的 AutocompleteCombobox

要仅获取有效条目(无自定义条目),您必须重新实现 AutocompleteCombobox 类的自动完成方法。
逻辑很简单:检查当前用户输入是否在自动完成列表中。如果没有,请删除最后一个字符并再次显示最后一个自动完成建议。

我使用此中的示例代码作为我的答案的基础。

以下是实现自定义 MatchOnlyAutocompleteCombobox 的代码片段:

from tkinter import *

from ttkwidgets.autocomplete import AutocompleteCombobox

countries = [
    'Antigua and Barbuda', 'Bahamas', 'Barbados', 'Belize', 'Canada',
    'Costa Rica ', 'Cuba', 'Dominica', 'Dominican Republic', 'El Salvador ',
    'Grenada', 'Guatemala ', 'Haiti', 'Honduras ', 'Jamaica', 'Mexico',
    'Nicaragua', 'Saint Kitts and Nevis', 'Panama ', 'Saint Lucia',
    'Saint Vincent and the Grenadines', 'Trinidad and Tobago', 'United States of America'
]

ws = Tk()
ws.title('PythonGuides')
ws.geometry('400x300')
ws.config(bg='#8DBF5A')


class MatchOnlyAutocompleteCombobox(AutocompleteCombobox):

    def autocomplete(self, delta=0):
        """
        Autocomplete the Combobox.

        :param delta: 0, 1 or -1: how to cycle through possible hits
        :type delta: int
        """
        if delta:  # need to delete selection otherwise we would fix the current position
            self.delete(self.position, END)
        else:  # 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()):  # Match case insensitively
                _hits.append(element)

        if not _hits:
            # No hits with current user text input
            self.position -= 1  # delete one character
            self.delete(self.position, END)
            # Display again last matched autocomplete
            self.autocomplete(delta)
            return

        # 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 + delta) % len(self._hits)
        # now finally perform the auto completion
        if self._hits:
            self.delete(0, END)
            self.insert(0, self._hits[self._hit_index])
            self.select_range(self.position, END)


frame = Frame(ws, bg='#8DBF5A')
frame.pack(expand=True)

Label(
    frame,
    bg='#8DBF5A',
    font=('Times', 21),
    text='Countries in North America '
).pack()

entry = MatchOnlyAutocompleteCombobox(
    frame,
    width=30,
    font=('Times', 18),
    completevalues=countries
)
entry.pack()

ws.mainloop()

Since You didn't provide example code and tkinter does not provide default autocomplete combobx, I assumed You are using AutocompleteCombobox from ttkwidgets.autocomplete.

To get only valid entries (no custom one), You have to re-implement autocomplete method of AutocompleteCombobox class.
Logic is simple: check if current user input is in autocomplete list. If not, remove last character and show again last autocomplete suggestion.

I used example code from this source as a base for my answer.

Here is code snippet implementing custom MatchOnlyAutocompleteCombobox:

from tkinter import *

from ttkwidgets.autocomplete import AutocompleteCombobox

countries = [
    'Antigua and Barbuda', 'Bahamas', 'Barbados', 'Belize', 'Canada',
    'Costa Rica ', 'Cuba', 'Dominica', 'Dominican Republic', 'El Salvador ',
    'Grenada', 'Guatemala ', 'Haiti', 'Honduras ', 'Jamaica', 'Mexico',
    'Nicaragua', 'Saint Kitts and Nevis', 'Panama ', 'Saint Lucia',
    'Saint Vincent and the Grenadines', 'Trinidad and Tobago', 'United States of America'
]

ws = Tk()
ws.title('PythonGuides')
ws.geometry('400x300')
ws.config(bg='#8DBF5A')


class MatchOnlyAutocompleteCombobox(AutocompleteCombobox):

    def autocomplete(self, delta=0):
        """
        Autocomplete the Combobox.

        :param delta: 0, 1 or -1: how to cycle through possible hits
        :type delta: int
        """
        if delta:  # need to delete selection otherwise we would fix the current position
            self.delete(self.position, END)
        else:  # 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()):  # Match case insensitively
                _hits.append(element)

        if not _hits:
            # No hits with current user text input
            self.position -= 1  # delete one character
            self.delete(self.position, END)
            # Display again last matched autocomplete
            self.autocomplete(delta)
            return

        # 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 + delta) % len(self._hits)
        # now finally perform the auto completion
        if self._hits:
            self.delete(0, END)
            self.insert(0, self._hits[self._hit_index])
            self.select_range(self.position, END)


frame = Frame(ws, bg='#8DBF5A')
frame.pack(expand=True)

Label(
    frame,
    bg='#8DBF5A',
    font=('Times', 21),
    text='Countries in North America '
).pack()

entry = MatchOnlyAutocompleteCombobox(
    frame,
    width=30,
    font=('Times', 18),
    completevalues=countries
)
entry.pack()

ws.mainloop()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文