gpt4 book ai didi

python-2.7 - 带有 LIKE 搜索的 Python Tkinter 自动完成组合框?

转载 作者:行者123 更新时间:2023-12-03 23:37:28 28 4
gpt4 key购买 nike

我正在尝试使用预定义的值填充 Tkinter 组合框以供选择。它正在填充,我可以输入并获得建议。但是,为了做到这一点,我必须肯定知道前几个字符。如果我知道字符串中间或末尾的一些文本,它就没有用,因为组合框只进行 'LIKE%' 搜索而不是 '%LIKE%' 搜索

预期输出(键入单词“Ceramic”会获取包含该字符串的所有名称。注意:这不是 Tkinter 屏幕截图):

enter image description here

这是我迄今为止对代码的改编,如果有人能建议如何修改 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在正确的位置。


编辑: 示例如何使用 EntryListbox显示过滤列表

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()

从完整列表开始

enter image description here

稍后仅使用过滤后的项目

enter image description here


编辑:2020.07.21

如果您想使用 <KeyPress>那么你必须改变 on_keyrelease并使用 event.char , event.keysym和/或 event.keycode因为KeyPresstkinter 之前执行更新 Entry 中的文本你必须添加event.charEntry 中发短信(或按 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()

顺便说一句:

您也可以使用textvariableEntryStringVartraceStringVar 时执行函数改变内容。

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/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com