@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
) だけを含む新しいモデルを与えます。非常に大きなモデルを扱っている場合、これはパフォーマンスの問題につながる可能性がありますが、私にとってはハックはうまく機能します。
更新 2:
コンボボックスに新しい文字列を入力してユーザーが Enter キーを押すと、コンボボックスが再びクリアされるため、これはまだ完璧な方法ではないことに気付きました。新しい文字列を入力する唯一の方法は、入力後にドロップダウン メニューから選択することです。
更新 3:
入力も機能するようになりました。ユーザーがEnterキーを押したときにコンボボックスのテキストをオフにするだけで、コンボボックスのテキストのリセットを回避しました。しかし、補完機能がそのまま残るように、元に戻しました。ユーザーがさらに編集を行うことにした場合。