Sobre la base de la respuesta de @Bruno, estoy usando el estándar QSortFilterProxyModel
setFilterRegExp
función para cambiar la cadena de búsqueda. De esta forma, no es necesario subclasificar.
También corrige un error en la respuesta de @ Bruno, lo que hizo desaparecer las sugerencias por alguna razón una vez que la cadena de entrada se corrigió con el retroceso mientras se escribía.
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)
Actualización:
que pensé que mi solución anterior trabajó hasta la cadena en el cuadro combinado corresponde ninguno de los elementos de la lista. Luego, el QFilterProxyModel
estaba vacío y esto a su vez restableció el text
del cuadro combinado. Traté de encontrar una solución elegante a este problema, pero me encontré con problemas (haciendo referencia a los errores de objetos eliminados) cada vez que intenté cambiar algo en self.filterProxyModel
. Así que ahora el truco es establecer el modelo de self.filterProxyModel
cada vez que se actualiza cuando se actualiza su patrón. Y cada vez que el patrón ya no coincide con nada en el modelo, para darle un nuevo modelo que solo contenga el texto actual (también conocido como path
en splitPath
). Esto puede ocasionar problemas de rendimiento si se trata de modelos muy grandes, pero para mí el truco funciona bastante bien.
Actualización 2:
me di cuenta de que esto todavía no es el camino perfecto para ir, porque si una nueva cadena se escribe en el cuadro combinado y el usuario pulsa Intro, el cuadro combinado se borra de nuevo. La única forma de ingresar una nueva cadena es seleccionarla del menú desplegable después de escribir.
Actualización 3:
Ahora entrar en las obras también. Trabajé alrededor del reinicio del texto del combobox simplemente quitándolo de la carga cuando el usuario presiona enter. Pero lo vuelvo a poner, para que la funcionalidad de finalización permanezca en su lugar. Si el usuario decide hacer más ediciones.
cosas buenas. si uno quiere usarlo, asegúrese de establecer todas las opciones en el cuadro combinado y completar como en el código mostrado arriba –
Extendí su solución en una respuesta separada, porque experimento un error en su solución. El cuadro combinado sugiere los elementos correctos mientras escribe. Pero tan pronto como toco el retroceso para corregir la cadena que estoy buscando, el cuadro combinado ya no sugiere ningún elemento. –