- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用预定义的值填充 Tkinter 组合框以供选择。它正在填充,我可以输入并获得建议。但是,为了做到这一点,我必须肯定知道前几个字符。如果我知道字符串中间或末尾的一些文本,它就没有用,因为组合框只进行 'LIKE%' 搜索而不是 '%LIKE%' 搜索。
预期输出(键入单词“Ceramic”会获取包含该字符串的所有名称。注意:这不是 Tkinter 屏幕截图):
这是我迄今为止对代码的改编,如果有人能建议如何修改 AutocompleteCombobox 类来进行 LIKE 搜索,那就太好了。
下面的工作代码,例如,具有值 "Cranberry"和 "Strawberry",我的要求是输入 "berry"并获得两种水果的建议。
import Tkinter
import ttk
import sqlite3
class AutocompleteCombobox(ttk.Combobox):
def set_completion_list(self, completion_list):
"""Use our completion list as our drop down selection menu, arrows move through menu."""
self._completion_list = sorted(completion_list, key=str.lower) # Work with a sorted list
self._hits = []
self._hit_index = 0
self.position = 0
self.bind('<KeyRelease>', self.handle_keyrelease)
self['values'] = self._completion_list # Setup our popup menu
def autocomplete(self, delta=0):
"""autocomplete the Combobox, delta may be 0/1/-1 to cycle through possible hits"""
if delta: # need to delete selection otherwise we would fix the current position
self.delete(self.position, Tkinter.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 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,Tkinter.END)
self.insert(0,self._hits[self._hit_index])
self.select_range(self.position,Tkinter.END)
def handle_keyrelease(self, event):
"""event handler for the keyrelease event on this widget"""
if event.keysym == "BackSpace":
self.delete(self.index(Tkinter.INSERT), Tkinter.END)
self.position = self.index(Tkinter.END)
if event.keysym == "Left":
if self.position < self.index(Tkinter.END): # delete the selection
self.delete(self.position, Tkinter.END)
else:
self.position = self.position-1 # delete one character
self.delete(self.position, Tkinter.END)
if event.keysym == "Right":
self.position = self.index(Tkinter.END) # go to end (no selection)
if len(event.keysym) == 1:
self.autocomplete()
# No need for up/down, we'll jump to the popup
# list at the position of the autocompletion
def test(test_list):
"""Run a mini application to test the AutocompleteEntry Widget."""
root = Tkinter.Tk(className='AutocompleteCombobox')
combo = AutocompleteCombobox(root)
combo.set_completion_list(test_list)
combo.pack()
combo.focus_set()
# I used a tiling WM with no controls, added a shortcut to quit
root.bind('<Control-Q>', lambda event=None: root.destroy())
root.bind('<Control-q>', lambda event=None: root.destroy())
root.mainloop()
if __name__ == '__main__':
test_list = ('apple', 'banana', 'Cranberry', 'dogwood', 'alpha', 'Acorn', 'Anise', 'Strawberry' )
test(test_list)
最佳答案
我怀疑你需要
if self.get().lower() in element.lower():
而不是
if element.lower().startswith(self.get().lower()):
获取数据,如 %LIKE%
在数据库中
但是不知道效果好不好因为这个Combobox
用建议替换文本,所以如果你输入 be
然后找到 Cranberry
并到位be
你不能写ber
.
也许你应该显示 Cranberry
作为分隔(下拉)列表或弹出提示。
或者你可能不得不使用 string.find()
突出显示 Cranberry
中的正确位置并继续输入 ber
在正确的位置。
编辑: 示例如何使用 Entry
和 Listbox
显示过滤列表
在 listbox_update
我添加了排序列表(比较小写字符串)
#!/usr/bin/env python3
import tkinter as tk
def on_keyrelease(event):
# get text from entry
value = event.widget.get()
value = value.strip().lower()
# get data from test_list
if value == '':
data = test_list
else:
data = []
for item in test_list:
if value in item.lower():
data.append(item)
# update data in listbox
listbox_update(data)
def listbox_update(data):
# delete previous data
listbox.delete(0, 'end')
# sorting data
data = sorted(data, key=str.lower)
# put new data
for item in data:
listbox.insert('end', item)
def on_select(event):
# display element selected on list
print('(event) previous:', event.widget.get('active'))
print('(event) current:', event.widget.get(event.widget.curselection()))
print('---')
# --- main ---
test_list = ('apple', 'banana', 'Cranberry', 'dogwood', 'alpha', 'Acorn', 'Anise', 'Strawberry' )
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
entry.bind('<KeyRelease>', on_keyrelease)
listbox = tk.Listbox(root)
listbox.pack()
#listbox.bind('<Double-Button-1>', on_select)
listbox.bind('<<ListboxSelect>>', on_select)
listbox_update(test_list)
root.mainloop()
从完整列表开始
稍后仅使用过滤后的项目
编辑:2020.07.21
如果您想使用 <KeyPress>
那么你必须改变 on_keyrelease
并使用 event.char
, event.keysym
和/或 event.keycode
因为KeyPress
在 tkinter
之前执行更新 Entry
中的文本你必须添加event.char
在 Entry
中发短信(或按 backspace
时删除最后一个字符)
if event.keysym == 'BackSpace':
value = event.widget.get()[:-1] # remove last char
else:
value = event.widget.get() + event.char # add new char at the end
可能需要对其他特殊键进行其他更改 Ctrl+A
, Ctrl+X
, Ctrl+C
, Ctrl+E
等,这会造成很大的问题。
#!/usr/bin/env python3
import tkinter as tk
def on_keypress(event):
print(event)
print(event.state & 4) # Control
print(event.keysym == 'a')
# get text from entry
if event.keysym == 'BackSpace':
# remove last char
value = event.widget.get()[:-1]
elif (event.state & 4): # and (event.keysym in ('a', 'c', 'x', 'e')):
value = event.widget.get()
else:
# add new char at the end
value = event.widget.get() + event.char
#TODO: other special keys
value = value.strip().lower()
# get data from test_list
if value == '':
data = test_list
else:
data = []
for item in test_list:
if value in item.lower():
data.append(item)
# update data in listbox
listbox_update(data)
def listbox_update(data):
# delete previous data
listbox.delete(0, 'end')
# sorting data
data = sorted(data, key=str.lower)
# put new data
for item in data:
listbox.insert('end', item)
def on_select(event):
# display element selected on list
print('(event) previous:', event.widget.get('active'))
print('(event) current:', event.widget.get(event.widget.curselection()))
print('---')
# --- main ---
test_list = ('apple', 'banana', 'Cranberry', 'dogwood', 'alpha', 'Acorn', 'Anise', 'Strawberry' )
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
entry.bind('<KeyPress>', on_keypress)
listbox = tk.Listbox(root)
listbox.pack()
#listbox.bind('<Double-Button-1>', on_select)
listbox.bind('<<ListboxSelect>>', on_select)
listbox_update(test_list)
root.mainloop()
顺便说一句:
您也可以使用textvariable
在 Entry
与 StringVar
和 trace
在 StringVar
时执行函数改变内容。
var_text = tk.StringVar()
var_text.trace('w', on_change)
entry = tk.Entry(root, textvariable=var_text)
entry.pack()
#!/usr/bin/env python3
import tkinter as tk
def on_change(*args):
#print(args)
value = var_text.get()
value = value.strip().lower()
# get data from test_list
if value == '':
data = test_list
else:
data = []
for item in test_list:
if value in item.lower():
data.append(item)
# update data in listbox
listbox_update(data)
def listbox_update(data):
# delete previous data
listbox.delete(0, 'end')
# sorting data
data = sorted(data, key=str.lower)
# put new data
for item in data:
listbox.insert('end', item)
def on_select(event):
# display element selected on list
print('(event) previous:', event.widget.get('active'))
print('(event) current:', event.widget.get(event.widget.curselection()))
print('---')
# --- main ---
test_list = ('apple', 'banana', 'Cranberry', 'dogwood', 'alpha', 'Acorn', 'Anise', 'Strawberry' )
root = tk.Tk()
var_text = tk.StringVar()
var_text.trace('w', on_change)
entry = tk.Entry(root, textvariable=var_text)
entry.pack()
listbox = tk.Listbox(root)
listbox.pack()
#listbox.bind('<Double-Button-1>', on_select)
listbox.bind('<<ListboxSelect>>', on_select)
listbox_update(test_list)
root.mainloop()
关于python-2.7 - 带有 LIKE 搜索的 Python Tkinter 自动完成组合框?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47839813/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!