如果在StringVar上调用set(),则会调用绑定到tkinter小部件的两次()
问题描述:
我有一个条目,一个列表框(下拉列表)和另一个列表框。每当输入内输入3个以上的字符时。查看完成列表并将其插入到下拉列表中,并显示下拉列表。如果从下拉列表中选择一个项目。它的值应该填写条目,并且条目应该再次获得焦点,并且光标应该移到条目的末尾。然后,当按Enter键时,条目的值应该插入到另一个列表框中。如果在StringVar上调用set(),则会调用绑定到tkinter小部件的两次()
我已经为this实用程序提供了很多帮助,代码完美无缺。除此之外,我意识到,无论何时从下拉列表中选择一个选项,相应的方法都会被调用两次(我从控制台中获取两张相同的东西)。但是,如果我选择下拉菜单中的第一个选项,它会被调用一次(这是在其他情况下实际发生的情况),但焦点不会进入条目(这是一个问题)。
这里是我的代码:
from tkinter import *
class Autocomplete(Frame, object):
def __init__(self, width, height, entries, *args, **kwargs):
super(Autocomplete, self).__init__(*args, **kwargs)
self._entries = entries
self.listbox_height = height
self.entry_width = width
self.text = StringVar()
self.entry = Entry(
self,
textvariable=self.text,
width=self.entry_width
)
self.frame = Frame(self)
self.listbox = Listbox(
self.frame,
height=self.listbox_height,
width=self.entry_width
)
self.dropdown = Listbox(
self.frame,
height=self.listbox_height,
width=self.entry_width,
background="#cfeff9"
)
def build(self):
self.text.trace("w", lambda name, index, mode, text=self.text: self._update_autocomplete())
self.entry.bind("<Return>", lambda event,: self._add_course())
self.entry.focus_set()
self.entry.pack()
self.frame.pack()
self.listbox.grid(column=0, row=0, sticky=N)
self.dropdown.bind("<<ListboxSelect>>", self._select_entry)
self.dropdown.grid(column=0, row=0, sticky=N)
self.dropdown.grid_forget()
return self
def _update_autocomplete(self):
self.dropdown["height"] = self.listbox_height
self.dropdown.delete(0, END)
text = self.text.get()
if len(text) < 3:
self.dropdown.grid_forget()
return
else:
for entry in self._entries:
if text.lower() in entry.strip().lower():
self.dropdown.insert(END, entry)
listbox_size = self.dropdown.size()
if not listbox_size:
self.dropdown.insert(END, "No results found for '{}'")
self.dropdown["height"] = 1
else:
if listbox_size <= self.dropdown["height"]:
self.dropdown["height"] = listbox_size
self.dropdown.grid(column=0, row=0, sticky=N)
def _select_entry(self, event):
widget = event.widget
value = widget.get(int(widget.curselection()[0]))
print(value)
self.text.set(value)
self.entry.focus_set()
self.entry.icursor(END)
def _add_course(self):
self.listbox.insert(END, self.text.get())
那我在这里失踪?
顺便说一句,代码的任何一般的改进也将非常感激。
这里是我怎么称呼它:当你点击该项目
from tkinter import *
from autocomplete import Autocomplete
from main import *
courses = load_courses_from_file("courses.txt")
root = Tk()
autocomplete_frame = Autocomplete(
60,
10,
list(set(course.name + ", " + course.instructor for course in courses))
).build().pack()
mainloop()
答
ListBox的选择改变 - 这是列表框的默认行为。这会导致条目窗口小部件值发生更改,从而触发_update_autocomplete
的呼叫。该函数删除列表框中的所有内容,导致选择再次更改。
+0
我明白了!点击第一个元素时,所选元素的编号保持为1,因此它不会改变。尽管我仍然不明白为什么焦点没有改变。我该如何解决这个问题。 –
您的代码将不会以发布的方式运行。 –
@BryanOakley你是什么意思?你的意思是我没有打电话吗?如果是的话我编辑了这篇文章。否则,你确定吗? BC我想我正在运行它,我想我复制粘贴代码! –