鱼C论坛

 找回密码
 立即注册
查看: 4227|回复: 30

Combobox怎么实现模糊匹配?

[复制链接]
发表于 2021-1-8 08:33:39 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
下拉列表中有多个选项,怎么实现输入部分字符后自动将最接近的选项调到下拉列表的第一位?
或者通过其他方法达到类似的功能也行

例如我输入Pn7,自动将Pn789调到下拉列表的第一位
20210108083115.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-1-8 08:53:50 | 显示全部楼层
你说的应该是一个事件,内容改变事件,具体代码百度下。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 09:04:03 | 显示全部楼层
本帖最后由 qq1151985918 于 2021-1-8 09:05 编辑

我从网上给你找了个,用的是PyQt5
  1. from PyQt5 import QtCore, QtGui, QtWidgets
  2. from PyQt5.QtCore import Qt, QSortFilterProxyModel
  3. from PyQt5.QtWidgets import QCompleter, QComboBox

  4. class ExtendedComboBox(QComboBox):
  5.     def __init__(self, parent=None):
  6.         super(ExtendedComboBox, self).__init__(parent)

  7.         self.setFocusPolicy(Qt.StrongFocus)
  8.         self.setEditable(True)

  9.         # add a filter model to filter matching items
  10.         self.pFilterModel = QSortFilterProxyModel(self)
  11.         self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
  12.         self.pFilterModel.setSourceModel(self.model())

  13.         # add a completer, which uses the filter model
  14.         self.completer = QCompleter(self.pFilterModel, self)
  15.         # always show all (filtered) completions
  16.         self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
  17.         self.setCompleter(self.completer)

  18.         # connect signals
  19.         self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
  20.         self.completer.activated.connect(self.on_completer_activated)


  21.     # on selection of an item from the completer, select the corresponding item from combobox
  22.     def on_completer_activated(self, text):
  23.         if text:
  24.             index = self.findText(text)
  25.             self.setCurrentIndex(index)
  26.             self.activated[str].emit(self.itemText(index))


  27.     # on model change, update the models of the filter and completer as well
  28.     def setModel(self, model):
  29.         super(ExtendedComboBox, self).setModel(model)
  30.         self.pFilterModel.setSourceModel(model)
  31.         self.completer.setModel(self.pFilterModel)


  32.     # on model column change, update the model column of the filter and completer as well
  33.     def setModelColumn(self, column):
  34.         self.completer.setCompletionColumn(column)
  35.         self.pFilterModel.setFilterKeyColumn(column)
  36.         super(ExtendedComboBox, self).setModelColumn(column)


  37. if __name__ == "__main__":
  38.     import sys
  39.     from PyQt5.QtWidgets import QApplication
  40.     from PyQt5.QtCore import QStringListModel

  41.     app = QApplication(sys.argv)

  42.     string_list = ['语文 Chinese', '数学 Mathematics', '英语 English']

  43.     combo = ExtendedComboBox()

  44.     # either fill the standard model of the combobox
  45.     combo.addItems(string_list)

  46.     # or use another model
  47.     #combo.setModel(QStringListModel(string_list))

  48.     combo.resize(300, 40)
  49.     combo.show()

  50.     sys.exit(app.exec_())
复制代码

原文见链接  pyQt5 QcomboBox 下拉选项模糊搜索
https://www.cnblogs.com/6min/articles/10751959.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2021-1-8 09:11:45 | 显示全部楼层
z5560636 发表于 2021-1-8 08:53
你说的应该是一个事件,内容改变事件,具体代码百度下。

搜了一下这方面的资料很少,沒找到tkinter的combobox的相关操作...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 09:12:48 | 显示全部楼层
qq1151985918 发表于 2021-1-8 09:04
我从网上给你找了个,用的是PyQt5

原文见链接  pyQt5 QcomboBox 下拉选项模糊搜索

感谢!~~
效果OK,还不会pyqt,我看看先
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 09:23:19 | 显示全部楼层
本帖最后由 qq1151985918 于 2021-1-8 09:28 编辑
lengyue869 发表于 2021-1-8 09:11
搜了一下这方面的资料很少,沒找到tkinter的combobox的相关操作...


楼主你贴的图片是你自己写的效果图吗?有没有代码看一下?你怎么实现的输入文字显示下拉列表内容?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 09:38:52 | 显示全部楼层
qq1151985918 发表于 2021-1-8 09:23
楼主你贴的图片是你自己写的效果图吗?有没有代码看一下?你怎么实现的输入文字显示下拉列表内容?


  1. from tkinter import ttk
  2. import tkinter as tk

  3. root = tk.Tk()
  4. root.geometry('850x400+300+100')

  5. comb1Text = tk.StringVar()
  6. comb2Text = tk.StringVar()
  7. etyText = tk.StringVar()


  8. def com1_select(*args):
  9.     print(comb1.get())
  10.     return comb1.get()


  11. def com2_select(*args):
  12.     print(comb2.get())
  13.     return comb2.get()


  14. # PN下拉框
  15. comb1 = ttk.Combobox(root, textvariable=comb1Text, width=70)
  16. comb1["values"] = ['Pn123', 'Pn456', 'Pn789']
  17. comb1.bind("<<ComboboxSelected>>", com1_select)
  18. pn = com1_select()

  19. # user configuration下拉框
  20. comb2 = ttk.Combobox(root, textvariable=comb2Text, width=70)
  21. comb2["values"] = ['A', 'B', 'C']
  22. comb2.bind("<<ComboboxSelected>>", com2_select)
  23. user = com2_select()

  24. tk.Label(root, text='BOM PN & Ver:').grid(row=0, column=0)
  25. tk.Label(root, text='').grid(row=1, column=0)
  26. tk.Label(root, text='User Configuration:').grid(row=2, column=0)

  27. comb1.grid(row=0, column=1)
  28. comb2.grid(row=2, column=1)

  29. root.mainloop()
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 09:48:04 | 显示全部楼层

原来你没能做到输入文字显示下拉列表内容,我说嘛,如果做到这个要求了应该就能做到模糊匹配了,因为我直觉感觉如果Combobox如果有一个textchange事件或者能够实现的话,就能够做到模糊匹配了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 09:57:31 | 显示全部楼层
qq1151985918 发表于 2021-1-8 09:48
原来你没能做到输入文字显示下拉列表内容,我说嘛,如果做到这个要求了应该就能做到模糊匹配了,因为我直 ...

额,我再找找combobox的教程看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 10:03:52 | 显示全部楼层
找到了一个,哈哈
  1. import tkinter
  2. from tkinter import ttk


  3. class AutocompleteCombobox(ttk.Combobox):

  4.         def set_completion_list(self, completion_list):
  5.                 """Use our completion list as our drop down selection menu, arrows move through menu."""
  6.                 self._completion_list = sorted(completion_list, key=str.lower) # Work with a sorted list
  7.                 self._hits = []
  8.                 self._hit_index = 0
  9.                 self.position = 0
  10.                 self.bind('<KeyRelease>', self.handle_keyrelease)
  11.                 self['values'] = self._completion_list  # Setup our popup menu

  12.         def autocomplete(self, delta=0):
  13.                 """autocomplete the Combobox, delta may be 0/1/-1 to cycle through possible hits"""
  14.                 if delta: # need to delete selection otherwise we would fix the current position
  15.                         self.delete(self.position, tkinter.END)
  16.                 else: # set position to end so selection starts where textentry ended
  17.                         self.position = len(self.get())
  18.                 # collect hits
  19.                 _hits = []
  20.                 for element in self._completion_list:
  21.                         if element.lower().startswith(self.get().lower()): # Match case insensitively
  22.                                 _hits.append(element)
  23.                 # if we have a new hit list, keep this in mind
  24.                 if _hits != self._hits:
  25.                         self._hit_index = 0
  26.                         self._hits=_hits
  27.                 # only allow cycling if we are in a known hit list
  28.                 if _hits == self._hits and self._hits:
  29.                         self._hit_index = (self._hit_index + delta) % len(self._hits)
  30.                 # now finally perform the auto completion
  31.                 if self._hits:
  32.                         self.delete(0,tkinter.END)
  33.                         self.insert(0,self._hits[self._hit_index])
  34.                         self.select_range(self.position,tkinter.END)

  35.         def handle_keyrelease(self, event):
  36.                 """event handler for the keyrelease event on this widget"""
  37.                 if event.keysym == "BackSpace":
  38.                         self.delete(self.index(tkinter.INSERT), tkinter.END)
  39.                         self.position = self.index(tkinter.END)
  40.                 if event.keysym == "Left":
  41.                         if self.position < self.index(tkinter.END): # delete the selection
  42.                                 self.delete(self.position, tkinter.END)
  43.                         else:
  44.                                 self.position = self.position-1 # delete one character
  45.                                 self.delete(self.position, tkinter.END)
  46.                 if event.keysym == "Right":
  47.                         self.position = self.index(tkinter.END) # go to end (no selection)
  48.                 if len(event.keysym) == 1:
  49.                         self.autocomplete()
  50.                 # No need for up/down, we'll jump to the popup
  51.                 # list at the position of the autocompletion


  52. def test(test_list):
  53.         """Run a mini application to test the AutocompleteEntry Widget."""
  54.         root = tkinter.Tk(className='AutocompleteCombobox')

  55.         combo = AutocompleteCombobox(root)
  56.         combo.set_completion_list(test_list)
  57.         combo.pack()
  58.         combo.focus_set()
  59.         # I used a tiling WM with no controls, added a shortcut to quit
  60.         root.bind('<Control-Q>', lambda event=None: root.destroy())
  61.         root.bind('<Control-q>', lambda event=None: root.destroy())
  62.         root.mainloop()

  63. if __name__ == '__main__':
  64.         test_list = ('apple', 'banana', 'Cranberry', 'dogwood', 'alpha', 'Acorn', 'Anise', 'Strawberry' )
  65.         test(test_list)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 10:12:21 | 显示全部楼层

我试了下,这个不应该算作模糊搜索,应该算输入提示,比如 要搜索banana  ,
模糊搜索应该是输入ana    nan  都可以
不过应该可以 在这个基础上修改了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 10:23:11 | 显示全部楼层
qq1151985918 发表于 2021-1-8 10:12
我试了下,这个不应该算作模糊搜索,应该算输入提示,比如 要搜索banana  ,
模糊搜索应该是输入ana     ...

是的,不过看起来好像很复杂的样子....
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 10:32:37 | 显示全部楼层
qq1151985918 发表于 2021-1-8 10:12
我试了下,这个不应该算作模糊搜索,应该算输入提示,比如 要搜索banana  ,
模糊搜索应该是输入ana     ...

还是PyQt5那个效果好一些,要是能移植到tkinter上来就好了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 10:50:19 | 显示全部楼层
lengyue869 发表于 2021-1-8 10:32
还是PyQt5那个效果好一些,要是能移植到tkinter上来就好了

我先研究研究能不能把你刚刚搜索到的修改一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 10:54:28 | 显示全部楼层
qq1151985918 发表于 2021-1-8 10:50
我先研究研究能不能把你刚刚搜索到的修改一下

那真是太感谢了!~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 11:07:51 | 显示全部楼层
lengyue869 发表于 2021-1-8 10:54
那真是太感谢了!~

只能说是尝试
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 11:17:03 | 显示全部楼层

那也感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 12:13:30 | 显示全部楼层
lengyue869 发表于 2021-1-8 10:54
那真是太感谢了!~

抱歉,我改了半天,只能实现得很不完善,我想或许我得加入re来改,实在是太没有必要,因为这还得配合Combobox的其他用法和事件相配合,我功夫还不够...暂时改不成了,或许论坛的大神们出手可以。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-1-8 12:18:59 | 显示全部楼层
qq1151985918 发表于 2021-1-8 12:13
抱歉,我改了半天,只能实现得很不完善,我想或许我得加入re来改,实在是太没有必要,因为这还得配合Comb ...

it's ok,不行的话就用pyqt的布局,我抽时间学下pyqt
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-8 12:27:54 | 显示全部楼层
lengyue869 发表于 2021-1-8 12:18
it's ok,不行的话就用pyqt的布局,我抽时间学下pyqt

你先研究着,我也还在想修改的办法,如果改成功了会告诉你
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-12 04:37

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表