jcu*_*nod 24 qt qt4 qcombobox qcompleter qt4.6
我正在使用Qt4.6,我有一个带QCompleter的QComboBox.
通常的功能是提供基于前缀的完成提示(这些提示可以是下拉列表而不是内联 - 这是我的用法).例如,给定
chicken soup
chilli peppers
grilled chicken
Run Code Online (Sandbox Code Playgroud)
进入ch
将匹配chicken soup
,chilli peppers
但不是grilled chicken
.
我想要的是能够输入ch
和匹配所有这些,或者更具体地说,chicken
匹配chicken soup
和grilled chicken
.
我也希望能够指定一个标签一样chs
,以chicken soup
产生另一场比赛这不仅是对文本的内容.我可以处理算法,但是,
我需要覆盖哪些QCompleter函数?
我不确定我应该在哪里看......
Bru*_*uno 10
根据@ j3frea建议,这是一个工作示例(使用PySide
).似乎每次splitPath
调用时都需要设置模型(设置代理一次setModel
就不起作用).
combobox.setEditable(True)
combobox.setInsertPolicy(QComboBox.NoInsert)
class CustomQCompleter(QCompleter):
def __init__(self, parent=None):
super(CustomQCompleter, self).__init__(parent)
self.local_completion_prefix = ""
self.source_model = None
def setModel(self, model):
self.source_model = model
super(CustomQCompleter, self).setModel(self.source_model)
def updateModel(self):
local_completion_prefix = self.local_completion_prefix
class InnerProxyModel(QSortFilterProxyModel):
def filterAcceptsRow(self, sourceRow, sourceParent):
index0 = self.sourceModel().index(sourceRow, 0, sourceParent)
return local_completion_prefix.lower() in self.sourceModel().data(index0).lower()
proxy_model = InnerProxyModel()
proxy_model.setSourceModel(self.source_model)
super(CustomQCompleter, self).setModel(proxy_model)
def splitPath(self, path):
self.local_completion_prefix = path
self.updateModel()
return ""
completer = CustomQCompleter(combobox)
completer.setCompletionMode(QCompleter.PopupCompletion)
completer.setModel(combobox.model())
combobox.setCompleter(completer)
Run Code Online (Sandbox Code Playgroud)
使用filterMode : Qt::MatchFlags
财产.此属性保存过滤的执行方式.如果filterMode设置为Qt::MatchStartsWith
,则仅显示以键入的字符开头的条目.Qt::MatchContains
将显示包含键入字符的条目,以及Qt::MatchEndsWith
以键入的字符结尾的条目.目前,只实现了这三种模式.将filterMode设置为任何其他Qt::MatchFlag
将发出警告,并且不会执行任何操作.默认模式是Qt::MatchStartsWith
.
该属性在Qt 5.2中引入.
访问功能:
Qt::MatchFlags filterMode() const
void setFilterMode(Qt::MatchFlags filterMode)
Run Code Online (Sandbox Code Playgroud)
基于@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)
Run Code Online (Sandbox Code Playgroud)
更新:
我认为我之前的解决方案有效,直到组合框中的字符串与列表项都没有匹配.然后QFilterProxyModel
是空的,这反过来重新text
组合了组合框.我试图找到这个问题的优雅解决方案,但每当我尝试更改某些内容时,我遇到了问题(引用已删除的对象错误)self.filterProxyModel
.所以现在黑客就是self.filterProxyModel
在模式更新时设置每次新模型.每当模式不再与模型中的任何东西匹配时,给它一个只包含当前文本(又名path
于splitPath
)的新模型.如果你正在处理非常大的模型,这可能会导致性能问题,但对我来说,黑客工作得很好.
更新2:
我意识到这仍然不是一个完美的方法,因为如果在组合框中键入一个新字符串并且用户按下回车键,组合框将再次被清除.输入新字符串的唯一方法是在输入后从下拉菜单中选择它.
更新3:
现在进入工作.当用户按下回车键时,我只需将其取下即可完成组合框文本的重置.但我把它重新放入,以便完成功能保持不变.如果用户决定进行进一步编辑.
归档时间: |
|
查看次数: |
11012 次 |
最近记录: |