Tkinter 文本自动填充
Tkinter Text Autofill
我正在尝试使用 tkinter 为 python 制作一个简单且个性化的 IDE。我以前看过它,并且将所有形式的语法突出显示到内置终端,但没有自动填充的问题。我知道您可以使用许多方法在条目中自动填充,但是在搜索带有文本条目的自动填充后,我找不到任何东西。如果我能得到一些帮助,那就太好了!我正在寻找类似于此处所见的内容。
类似思路代码:
from ttkwidgets.autocomplete import AutocompleteEntry
from tkinter import *
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='#f25252')
frame = Frame(ws, bg='#f25252')
frame.pack(expand=True)
Label(
frame,
bg='#f25252',
font = ('Times',21),
text='Countries in North America '
).pack()
entry = AutocompleteEntry(
frame,
width=30,
font=('Times', 18),
completevalues=countries
)
entry.pack()
ws.mainloop()
Link 到 AutocompleteEntry
的源代码
对于基本的自动完成功能,基本算法相当简单:
- 拦截键释放(在 tkinter 自动插入键入的文本后发生)
- 获取光标前的单词并调用回调以查找可能的匹配项
- 添加第一个可能的匹配项,以及 select 添加的部分以便将来的按键将替换它
您还可以为 Tab 键添加一个绑定,它将查看是否有可见的自动完成文本,并将光标移动到末尾。
这是一个非常hacked-together的示例来说明原理,尽管它缺乏任何防弹、优化或边缘情况的处理,例如退格、在单词中间键入、选择替代替换、等等
明确一点:这不是实现自动完成的最佳方式,它只是说明概念。
import tkinter as tk
class AutocompleteText(tk.Text):
def __init__(self, *args, **kwargs):
self.callback = kwargs.pop("autocomplete", None)
super().__init__(*args, **kwargs)
# bind on key release, which will happen after tkinter
# inserts the typed character
self.bind("<Any-KeyRelease>", self._autocomplete)
# special handling for tab, which needs to happen on the
# key _press_
self.bind("<Tab>", self._handle_tab)
def _handle_tab(self, event):
# see if any text has the "autocomplete" tag
tag_ranges= self.tag_ranges("autocomplete")
if tag_ranges:
# move the insertion cursor to the end of
# the selected text, and then remove the "sel"
# and "autocomplete" tags
self.mark_set("insert", tag_ranges[1])
self.tag_remove("sel", "1.0", "end")
self.tag_remove("autocomplete", "1.0", "end")
# prevent the default behavior of inserting a literal tab
return "break"
def _autocomplete(self, event):
if event.char and self.callback:
# get word preceeding the insertion cursor
word = self.get("insert-1c wordstart", "insert-1c wordend")
# pass word to callback to get possible matches
matches = self.callback(word)
if matches:
# autocomplete on the first match
remainder = matches[0][len(word):]
# remember the current insertion cursor
insert = self.index("insert")
# insert at the insertion cursor the remainder of
# the matched word, and apply the tag "sel" so that
# it is selected. Also, add the "autocomplete" text
# which will make it easier to find later.
self.insert(insert, remainder, ("sel", "autocomplete"))
# move the cursor back to the saved position
self.mark_set("insert", insert)
def get_matches(word):
# For illustrative purposes, pull possible matches from
# what has already been typed. You could just as easily
# return a list of pre-defined keywords.
words = text.get("1.0", "end-1c").split()
matches = [x for x in words if x.startswith(word)]
return matches
root = tk.Tk()
text = AutocompleteText(root, autocomplete=get_matches)
text.pack(fill="both", expand=True)
root.mainloop()
我正在尝试使用 tkinter 为 python 制作一个简单且个性化的 IDE。我以前看过它,并且将所有形式的语法突出显示到内置终端,但没有自动填充的问题。我知道您可以使用许多方法在条目中自动填充,但是在搜索带有文本条目的自动填充后,我找不到任何东西。如果我能得到一些帮助,那就太好了!我正在寻找类似于此处所见的内容。
类似思路代码:
from ttkwidgets.autocomplete import AutocompleteEntry
from tkinter import *
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='#f25252')
frame = Frame(ws, bg='#f25252')
frame.pack(expand=True)
Label(
frame,
bg='#f25252',
font = ('Times',21),
text='Countries in North America '
).pack()
entry = AutocompleteEntry(
frame,
width=30,
font=('Times', 18),
completevalues=countries
)
entry.pack()
ws.mainloop()
Link 到 AutocompleteEntry
的源代码对于基本的自动完成功能,基本算法相当简单:
- 拦截键释放(在 tkinter 自动插入键入的文本后发生)
- 获取光标前的单词并调用回调以查找可能的匹配项
- 添加第一个可能的匹配项,以及 select 添加的部分以便将来的按键将替换它
您还可以为 Tab 键添加一个绑定,它将查看是否有可见的自动完成文本,并将光标移动到末尾。
这是一个非常hacked-together的示例来说明原理,尽管它缺乏任何防弹、优化或边缘情况的处理,例如退格、在单词中间键入、选择替代替换、等等
明确一点:这不是实现自动完成的最佳方式,它只是说明概念。
import tkinter as tk
class AutocompleteText(tk.Text):
def __init__(self, *args, **kwargs):
self.callback = kwargs.pop("autocomplete", None)
super().__init__(*args, **kwargs)
# bind on key release, which will happen after tkinter
# inserts the typed character
self.bind("<Any-KeyRelease>", self._autocomplete)
# special handling for tab, which needs to happen on the
# key _press_
self.bind("<Tab>", self._handle_tab)
def _handle_tab(self, event):
# see if any text has the "autocomplete" tag
tag_ranges= self.tag_ranges("autocomplete")
if tag_ranges:
# move the insertion cursor to the end of
# the selected text, and then remove the "sel"
# and "autocomplete" tags
self.mark_set("insert", tag_ranges[1])
self.tag_remove("sel", "1.0", "end")
self.tag_remove("autocomplete", "1.0", "end")
# prevent the default behavior of inserting a literal tab
return "break"
def _autocomplete(self, event):
if event.char and self.callback:
# get word preceeding the insertion cursor
word = self.get("insert-1c wordstart", "insert-1c wordend")
# pass word to callback to get possible matches
matches = self.callback(word)
if matches:
# autocomplete on the first match
remainder = matches[0][len(word):]
# remember the current insertion cursor
insert = self.index("insert")
# insert at the insertion cursor the remainder of
# the matched word, and apply the tag "sel" so that
# it is selected. Also, add the "autocomplete" text
# which will make it easier to find later.
self.insert(insert, remainder, ("sel", "autocomplete"))
# move the cursor back to the saved position
self.mark_set("insert", insert)
def get_matches(word):
# For illustrative purposes, pull possible matches from
# what has already been typed. You could just as easily
# return a list of pre-defined keywords.
words = text.get("1.0", "end-1c").split()
matches = [x for x in words if x.startswith(word)]
return matches
root = tk.Tk()
text = AutocompleteText(root, autocomplete=get_matches)
text.pack(fill="both", expand=True)
root.mainloop()