基于@Bruno 的答案,我正在使用标准QSortFilterProxyModel
函数setFilterRegExp
来更改搜索字符串。这样就不需要子分类了。
它还修复了@Bruno 的答案中的一个错误,一旦输入字符串在键入时用退格键更正,建议就会由于某些原因消失。
class CustomQCompleter(QtGui.QCompleter):
"""
adapted from: http://stackoverflow.com/a/7767999/2156909
"""
def __init__(self, *args):#parent=None):
super(CustomQCompleter, self).__init__(*args)
self.local_completion_prefix = ""
self.source_model = None
self.filterProxyModel = QtGui.QSortFilterProxyModel(self)
self.usingOriginalModel = False
def setModel(self, model):
self.source_model = model
self.filterProxyModel = QtGui.QSortFilterProxyModel(self)
self.filterProxyModel.setSourceModel(self.source_model)
super(CustomQCompleter, self).setModel(self.filterProxyModel)
self.usingOriginalModel = True
def updateModel(self):
if not self.usingOriginalModel:
self.filterProxyModel.setSourceModel(self.source_model)
pattern = QtCore.QRegExp(self.local_completion_prefix,
QtCore.Qt.CaseInsensitive,
QtCore.QRegExp.FixedString)
self.filterProxyModel.setFilterRegExp(pattern)
def splitPath(self, path):
self.local_completion_prefix = path
self.updateModel()
if self.filterProxyModel.rowCount() == 0:
self.usingOriginalModel = False
self.filterProxyModel.setSourceModel(QtGui.QStringListModel([path]))
return [path]
return []
class AutoCompleteComboBox(QtGui.QComboBox):
def __init__(self, *args, **kwargs):
super(AutoCompleteComboBox, self).__init__(*args, **kwargs)
self.setEditable(True)
self.setInsertPolicy(self.NoInsert)
self.comp = CustomQCompleter(self)
self.comp.setCompletionMode(QtGui.QCompleter.PopupCompletion)
self.setCompleter(self.comp)#
self.setModel(["Lola", "Lila", "Cola", 'Lothian'])
def setModel(self, strList):
self.clear()
self.insertItems(0, strList)
self.comp.setModel(self.model())
def focusInEvent(self, event):
self.clearEditText()
super(AutoCompleteComboBox, self).focusInEvent(event)
def keyPressEvent(self, event):
key = event.key()
if key == 16777220:
# Enter (if event.key() == QtCore.Qt.Key_Enter) does not work
# for some reason
# make sure that the completer does not set the
# currentText of the combobox to "" when pressing enter
text = self.currentText()
self.setCompleter(None)
self.setEditText(text)
self.setCompleter(self.comp)
return super(AutoCompleteComboBox, self).keyPressEvent(event)
更新:
我认为我以前的解决方案一直有效,直到组合框中的字符串与列表项都不匹配。然后QFilterProxyModel
是空的,这反过来又重置text
了组合框的。我试图找到一个优雅的解决方案来解决这个问题,但是每当我尝试在self.filterProxyModel
. 所以现在的技巧是在self.filterProxyModel
模式更新时设置每次新的模型。并且每当模式不再与模型中的任何内容匹配时,为其提供一个仅包含当前文本(又名path
in splitPath
)的新模型。如果您正在处理非常大的模型,这可能会导致性能问题,但对我来说,hack 效果很好。
更新 2:
我意识到这仍然不是一个完美的方法,因为如果在组合框中输入了一个新字符串并且用户按下回车键,组合框就会再次被清除。输入新字符串的唯一方法是在键入后从下拉菜单中选择它。
更新 3:
现在也输入作品。我解决了组合框文本的重置问题,只需在用户按下回车键时将其关闭即可。但是我把它放回去了,所以完成功能仍然存在。如果用户决定进行进一步的编辑。