在 Tkinter 中为自动完成条目小部件设置默认文本
Set Default Text for Autocomplete Entry Widget in Tkinter
我正在使用具有几个简单字段的 tkinter 构建 GUI。我想出了如何使用 Entry 小部件的 textvariable 参数为它们设置默认值(我将这些值从 .pickle 文件加载到字典中),但我构建了其中一个字段以在用户输入值时使用自动完成.这是一个单独的 class,我使用了我找到的代码 here。
我已经尝试了很多方法来在启动应用程序时在此小部件中加载值,例如返回值和使用 set() 方法,但我一直没有成功。我要么出错,要么什么都没有发生。我在小部件中输入的值确实已成功保存到我的 pickle 文件中。
我仍在使用 python 学习面向对象编程,所以请放轻松。那么我该如何修改下面的代码来显示默认值呢?
from Tkinter import *
import re
lista = ['a', 'actions', 'additional', 'also', 'an', 'and', 'angle', 'are', 'as', 'be', 'bind','bracket', 'brackets', 'button', 'can', 'cases', 'configure', 'course', 'detail', 'enter', 'event', 'events', 'example', 'field', 'fields', 'for', 'give', 'important', 'in', 'information', 'is', 'it', 'just', 'key', 'keyboard', 'kind', 'leave', 'left', 'like', 'manager', 'many', 'match', 'modifier', 'most', 'of', 'or', 'others', 'out', 'part', 'simplify', 'space', 'specifier', 'specifies', 'string;', 'that', 'the', 'there', 'to', 'type', 'unless', 'use', 'used', 'user', 'various', 'ways', 'we', 'window', 'wish', 'you']
class AutocompleteEntry(Entry):
def __init__(self, lista, *args, **kwargs):
Entry.__init__(self, *args, **kwargs)
self.lista = lista
self.var = self["textvariable"]
if self.var == '':
self.var = self["textvariable"] = StringVar()
self.var.trace('w', self.changed)
self.bind("<Right>", self.selection)
self.bind("<Up>", self.up)
self.bind("<Down>", self.down)
self.lb_up = False
def changed(self, name, index, mode):
if self.var.get() == '':
self.lb.destroy()
self.lb_up = False
else:
words = self.comparison()
if words:
if not self.lb_up:
self.lb = Listbox()
self.lb.bind("<Double-Button-1>", self.selection)
self.lb.bind("<Right>", self.selection)
self.lb.place(x=self.winfo_x(), y=self.winfo_y()+self.winfo_height())
self.lb_up = True
self.lb.delete(0, END)
for w in words:
self.lb.insert(END,w)
else:
if self.lb_up:
self.lb.destroy()
self.lb_up = False
def selection(self, event):
if self.lb_up:
self.var.set(self.lb.get(ACTIVE))
self.lb.destroy()
self.lb_up = False
self.icursor(END)
def up(self, event):
if self.lb_up:
if self.lb.curselection() == ():
index = '0'
else:
index = self.lb.curselection()[0]
if index != '0':
self.lb.selection_clear(first=index)
index = str(int(index)-1)
self.lb.selection_set(first=index)
self.lb.activate(index)
def down(self, event):
if self.lb_up:
if self.lb.curselection() == ():
index = '0'
else:
index = self.lb.curselection()[0]
if index != END:
self.lb.selection_clear(first=index)
index = str(int(index)+1)
self.lb.selection_set(first=index)
self.lb.activate(index)
def comparison(self):
pattern = re.compile('.*' + self.var.get() + '.*')
return [w for w in self.lista if re.match(pattern, w)]
if __name__ == '__main__':
root = Tk()
entry = AutocompleteEntry(lista, root)
entry.grid(row=0, column=0)
Button(text='nothing').grid(row=1, column=0)
Button(text='nothing').grid(row=2, column=0)
Button(text='nothing').grid(row=3, column=0)
root.mainloop()
好的,在分析这段代码几个小时后,我想出了如何使用 insert()
方法获取默认值。这样做后我的第一个问题是列表框在应用程序启动时默认情况下也处于活动状态。通过向 changed
函数添加另一个 if 条件,它不会打开列表框,直到值被清除。当我添加条件语句时,行 self.lb.destroy()
在字段被清除时抛出错误:
AttributeError: 'AutocompleteEntry' object has no attribute 'lb'
我不确定为什么会抛出这个错误,因为它在我添加条件之前起作用了。但是,lb
未在 class 或函数的其他任何地方定义。删除该行修复了错误,一切似乎都按预期工作。这是我所做的更改。如果其他人有更好的解决方案,请告诉我。
class AutocompleteEntry(Entry):
# add settings argument which is True or False
def __init__(self, lista, settings, *args, **kwargs):
Entry.__init__(self, *args, **kwargs)
self.lista = lista
# define the self.settings object
self.settings = settings
self.var = self["textvariable"]
if self.var == '':
self.var = self["textvariable"] = StringVar()
self.var.trace('w', self.changed)
self.bind("<Return>", self.selection)
self.bind("<Up>", self.up)
self.bind("<Down>", self.down)
self.lb_up = False
def changed(self, name, index, mode):
if self.var.get() == '':
# self.lb.destroy() - removed this line
self.lb_up = False
# change this variable to False once the field is cleared
self.settings = False
# add if condition - field is not empty and settings is True
elif self.var.get() != '' and self.settings == True:
self.lb_up = False
else:
words = self.comparison()
if words:
if not self.lb_up:
self.lb = Listbox()
self.lb.bind("<Double-Button-1>", self.selection)
self.lb.bind("<Return>", self.selection)
self.lb.place(x=self.winfo_x(), y=self.winfo_y()+self.winfo_height())
self.lb_up = True
self.lb.delete(0, END)
for w in words:
self.lb.insert(END,w)
else:
if self.lb_up:
self.lb.destroy()
self.lb_up = False
最后一部分:
if __name__ == '__main__':
root = Tk()
# define settings variable and add to AutoCompleteEntry arguments
settings = True
entry = AutocompleteEntry(lista, settings, root)
entry.insert(END, "this is the default value")
entry.grid(row=0, column=0)
Button(text='nothing').grid(row=1, column=0)
Button(text='nothing').grid(row=2, column=0)
Button(text='nothing').grid(row=3, column=0)
root.mainloop()
有一个现有的 AutocompleteEntry 小部件。
示例:
from ttkwidgets.autocomplete import AutocompleteEntry
import tkinter as tk
window = tk.Tk()
Label1 = tk.Label(window, text="Entry:")
Label1.pack(side='left', padx=10, pady=10)
test_values = ['one', 'two', 'three']
test_var = tk.StringVar(window)
test_var.set('Default Value')
Entry1 = AutocompleteEntry(window, width=20, textvariable=test_var, completevalues=test_values)
Entry1.pack(side='left', padx=10, pady=10)
window.mainloop()
我正在使用具有几个简单字段的 tkinter 构建 GUI。我想出了如何使用 Entry 小部件的 textvariable 参数为它们设置默认值(我将这些值从 .pickle 文件加载到字典中),但我构建了其中一个字段以在用户输入值时使用自动完成.这是一个单独的 class,我使用了我找到的代码 here。
我已经尝试了很多方法来在启动应用程序时在此小部件中加载值,例如返回值和使用 set() 方法,但我一直没有成功。我要么出错,要么什么都没有发生。我在小部件中输入的值确实已成功保存到我的 pickle 文件中。
我仍在使用 python 学习面向对象编程,所以请放轻松。那么我该如何修改下面的代码来显示默认值呢?
from Tkinter import *
import re
lista = ['a', 'actions', 'additional', 'also', 'an', 'and', 'angle', 'are', 'as', 'be', 'bind','bracket', 'brackets', 'button', 'can', 'cases', 'configure', 'course', 'detail', 'enter', 'event', 'events', 'example', 'field', 'fields', 'for', 'give', 'important', 'in', 'information', 'is', 'it', 'just', 'key', 'keyboard', 'kind', 'leave', 'left', 'like', 'manager', 'many', 'match', 'modifier', 'most', 'of', 'or', 'others', 'out', 'part', 'simplify', 'space', 'specifier', 'specifies', 'string;', 'that', 'the', 'there', 'to', 'type', 'unless', 'use', 'used', 'user', 'various', 'ways', 'we', 'window', 'wish', 'you']
class AutocompleteEntry(Entry):
def __init__(self, lista, *args, **kwargs):
Entry.__init__(self, *args, **kwargs)
self.lista = lista
self.var = self["textvariable"]
if self.var == '':
self.var = self["textvariable"] = StringVar()
self.var.trace('w', self.changed)
self.bind("<Right>", self.selection)
self.bind("<Up>", self.up)
self.bind("<Down>", self.down)
self.lb_up = False
def changed(self, name, index, mode):
if self.var.get() == '':
self.lb.destroy()
self.lb_up = False
else:
words = self.comparison()
if words:
if not self.lb_up:
self.lb = Listbox()
self.lb.bind("<Double-Button-1>", self.selection)
self.lb.bind("<Right>", self.selection)
self.lb.place(x=self.winfo_x(), y=self.winfo_y()+self.winfo_height())
self.lb_up = True
self.lb.delete(0, END)
for w in words:
self.lb.insert(END,w)
else:
if self.lb_up:
self.lb.destroy()
self.lb_up = False
def selection(self, event):
if self.lb_up:
self.var.set(self.lb.get(ACTIVE))
self.lb.destroy()
self.lb_up = False
self.icursor(END)
def up(self, event):
if self.lb_up:
if self.lb.curselection() == ():
index = '0'
else:
index = self.lb.curselection()[0]
if index != '0':
self.lb.selection_clear(first=index)
index = str(int(index)-1)
self.lb.selection_set(first=index)
self.lb.activate(index)
def down(self, event):
if self.lb_up:
if self.lb.curselection() == ():
index = '0'
else:
index = self.lb.curselection()[0]
if index != END:
self.lb.selection_clear(first=index)
index = str(int(index)+1)
self.lb.selection_set(first=index)
self.lb.activate(index)
def comparison(self):
pattern = re.compile('.*' + self.var.get() + '.*')
return [w for w in self.lista if re.match(pattern, w)]
if __name__ == '__main__':
root = Tk()
entry = AutocompleteEntry(lista, root)
entry.grid(row=0, column=0)
Button(text='nothing').grid(row=1, column=0)
Button(text='nothing').grid(row=2, column=0)
Button(text='nothing').grid(row=3, column=0)
root.mainloop()
好的,在分析这段代码几个小时后,我想出了如何使用 insert()
方法获取默认值。这样做后我的第一个问题是列表框在应用程序启动时默认情况下也处于活动状态。通过向 changed
函数添加另一个 if 条件,它不会打开列表框,直到值被清除。当我添加条件语句时,行 self.lb.destroy()
在字段被清除时抛出错误:
AttributeError: 'AutocompleteEntry' object has no attribute 'lb'
我不确定为什么会抛出这个错误,因为它在我添加条件之前起作用了。但是,lb
未在 class 或函数的其他任何地方定义。删除该行修复了错误,一切似乎都按预期工作。这是我所做的更改。如果其他人有更好的解决方案,请告诉我。
class AutocompleteEntry(Entry):
# add settings argument which is True or False
def __init__(self, lista, settings, *args, **kwargs):
Entry.__init__(self, *args, **kwargs)
self.lista = lista
# define the self.settings object
self.settings = settings
self.var = self["textvariable"]
if self.var == '':
self.var = self["textvariable"] = StringVar()
self.var.trace('w', self.changed)
self.bind("<Return>", self.selection)
self.bind("<Up>", self.up)
self.bind("<Down>", self.down)
self.lb_up = False
def changed(self, name, index, mode):
if self.var.get() == '':
# self.lb.destroy() - removed this line
self.lb_up = False
# change this variable to False once the field is cleared
self.settings = False
# add if condition - field is not empty and settings is True
elif self.var.get() != '' and self.settings == True:
self.lb_up = False
else:
words = self.comparison()
if words:
if not self.lb_up:
self.lb = Listbox()
self.lb.bind("<Double-Button-1>", self.selection)
self.lb.bind("<Return>", self.selection)
self.lb.place(x=self.winfo_x(), y=self.winfo_y()+self.winfo_height())
self.lb_up = True
self.lb.delete(0, END)
for w in words:
self.lb.insert(END,w)
else:
if self.lb_up:
self.lb.destroy()
self.lb_up = False
最后一部分:
if __name__ == '__main__':
root = Tk()
# define settings variable and add to AutoCompleteEntry arguments
settings = True
entry = AutocompleteEntry(lista, settings, root)
entry.insert(END, "this is the default value")
entry.grid(row=0, column=0)
Button(text='nothing').grid(row=1, column=0)
Button(text='nothing').grid(row=2, column=0)
Button(text='nothing').grid(row=3, column=0)
root.mainloop()
有一个现有的 AutocompleteEntry 小部件。
示例:
from ttkwidgets.autocomplete import AutocompleteEntry
import tkinter as tk
window = tk.Tk()
Label1 = tk.Label(window, text="Entry:")
Label1.pack(side='left', padx=10, pady=10)
test_values = ['one', 'two', 'three']
test_var = tk.StringVar(window)
test_var.set('Default Value')
Entry1 = AutocompleteEntry(window, width=20, textvariable=test_var, completevalues=test_values)
Entry1.pack(side='left', padx=10, pady=10)
window.mainloop()