下面介绍本人最喜欢的一个QCombobox类型——带搜索功能的下拉框QCombobox:ExtendedCombobox
废话不多说,直接上效果图GIF,如下:
(1)可以看到,该Qcombobox有编辑功能,在输入一些字符后,Qcombobox会弹出含有这些字符和列表,按回车后默认选择是下拉列表中的第一个。
(2)同时,该搜索功能可以支持输入子项中非首字母的部分,然后弹出含有该字符的所有列表项,如列表有【jj,jk,kk,kl】,输入k,会弹出【jk,kk,kl】下拉列表。
(3)搜索时,支持不区分字母大小写功能,这个在GIF没体现,有兴趣的可以改写Qcombobox原有的列表进行尝试。
(1)利用Qcompleter的自动补全功能和QSortFilterProxyModel的过滤功能。首先将Qcombobox的列表内容填到筛选器模型QSortFilterProxyModel中去,并设置大小写不敏感Qt.CaseInsensitive,然后为Qcombobox设置补全器Qcompleter,并设置它对大小写不敏感Qt.CaseInsensitive和始终显示所有补全的结果展示效果QCompleter.UnfilteredPopupcomletion。
# 添加筛选器模型来筛选匹配项
self.pFilterModel = QSortFilterProxyModel(self)
self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive) # 大小写不敏感
self.pFilterModel.setSourceModel(self.model())
# 添加一个使用筛选器模型的QCompleter
self.completer = QCompleter(self.pFilterModel, self)
# 始终显示所有(过滤后的)补全结果
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
self.completer.setCaseSensitivity(Qt.CaseInsensitive) # 不区分大小写
self.setCompleter(self.completer)
# Qcombobox编辑栏文本变化时对应的槽函数
self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
self.completer.activated.connect(self.on_completer_activated)
# 当在Qcompleter列表选中候,下拉框项目列表选择相应的子项目
def on_completer_activated(self, text):
if text:
index = self.findText(text)
self.setCurrentIndex(index)
(2)相应键盘按键事件,设置按下回车后是选中补全器展示列的首项,同时Qcombobox下拉框收起。
# 回应回车按钮事件
def keyPressEvent(self, e):
if e.key() == Qt.Key_Enter & e.key() == Qt.Key_Return:
text = self.currentText()
index = self.findText(text, Qt.MatchExactly | Qt.MatchCaseSensitive)
self.setCurrentIndex(index)
self.hidePopup()
super(ExtendedComboBox, self).keyPressEvent(e)
else:
super(ExtendedComboBox, self).keyPressEvent(e)
from PyQt5.QtWidgets import QWidget, QComboBox, QLineEdit, QApplication
from PyQt5.QtGui import QMouseEvent
from PyQt5.Qt import Qt, QRect, QCompleter, QSortFilterProxyModel
import sys
# 带搜索功能的下拉框
class ExtendedComboBox(QComboBox):
def __init__(self, parent=None):
super(ExtendedComboBox, self).__init__(parent)
# self.setFocusPolicy(Qt.StrongFocus)
self.setEditable(True)
# 添加筛选器模型来筛选匹配项
self.pFilterModel = QSortFilterProxyModel(self)
self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive) # 大小写不敏感
self.pFilterModel.setSourceModel(self.model())
# 添加一个使用筛选器模型的QCompleter
self.completer = QCompleter(self.pFilterModel, self)
# 始终显示所有(过滤后的)补全结果
self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
self.completer.setCaseSensitivity(Qt.CaseInsensitive) # 不区分大小写
self.setCompleter(self.completer)
# Qcombobox编辑栏文本变化时对应的槽函数
self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
self.completer.activated.connect(self.on_completer_activated)
# 当在Qcompleter列表选中候,下拉框项目列表选择相应的子项目
def on_completer_activated(self, text):
if text:
index = self.findText(text)
self.setCurrentIndex(index)
# self.activated[str].emit(self.itemText(index))
# 在模型更改时,更新过滤器和补全器的模型
def setModel(self, model):
super(ExtendedComboBox, self).setModel(model)
self.pFilterModel.setSourceModel(model)
self.completer.setModel(self.pFilterModel)
# 在模型列更改时,更新过滤器和补全器的模型列
def setModelColumn(self, column):
self.completer.setCompletionColumn(column)
self.pFilterModel.setFilterKeyColumn(column)
super(ExtendedComboBox, self).setModelColumn(column)
# 回应回车按钮事件
def keyPressEvent(self, e):
if e.key() == Qt.Key_Enter & e.key() == Qt.Key_Return:
text = self.currentText()
index = self.findText(text, Qt.MatchExactly | Qt.MatchCaseSensitive)
self.setCurrentIndex(index)
self.hidePopup()
super(ExtendedComboBox, self).keyPressEvent(e)
else:
super(ExtendedComboBox, self).keyPressEvent(e)
def run():
app = QApplication(sys.argv)
win = ExtendedComboBox()
l = ["", "1aew","2asd","3ewqr","3ewqc","2wqpu","1kjijhm", "4kjndw", "5ioijb","6eolv", "11ofmsw"]
win.addItems(l)
win.show()
sys.exit(app.exec_())
if __name__ == '__main__':
run()