从多列(其中一列)开始自动完成
Autocomplete from start of (one of) multiple columns
我有多个列的数据(如 "first name"/"surname" 或 "postal code"/"place name"),我现在想要(类似)一个qcompleter 仅从每列的开头匹配。
这意味着输入 "a" 会显示类似“Andrea Miller”或 "John Adams" 的建议,但不会显示 "Jane Doe" 或 "Tom Masters".
有什么实现方法的提示吗?
解决方法是禁用 QCompleter 过滤并使用 QSortFilterProxyModel 进行自定义过滤:
import sys
from PySide2 import QtCore, QtWidgets
class FilterModel(QtCore.QSortFilterProxyModel):
def __init__(self, parent=None):
super().__init__(parent)
self._prefix = ""
@property
def prefix(self):
return self._prefix
@prefix.setter
def prefix(self, prefix):
self._prefix = prefix.lower()
self.invalidateFilter()
def filterAcceptsRow(self, sourceRow, sourceParent):
if not self.prefix:
return True
text = (
self.sourceModel()
.index(sourceRow, self.filterKeyColumn(), sourceParent)
.data()
)
for word in text.split():
if word.lower().startswith(self.prefix):
return True
return False
class Completer(QtWidgets.QCompleter):
def setModel(self, model):
proxy_internal_model = FilterModel(self)
proxy_internal_model.setSourceModel(model)
model.setParent(proxy_internal_model)
super().setModel(proxy_internal_model)
def splitPath(self, path):
if isinstance(self.model(), FilterModel):
self.model().prefix = path
return [""]
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QLineEdit()
texts = ["Andrea Miller", "John Adams", "Jane Doe", "Tom Masters"]
completer = Completer(w)
completer.setModel(QtCore.QStringListModel(texts, w))
w.setCompleter(completer)
w.show()
sys.exit(app.exec_())
我有多个列的数据(如 "first name"/"surname" 或 "postal code"/"place name"),我现在想要(类似)一个qcompleter 仅从每列的开头匹配。
这意味着输入 "a" 会显示类似“Andrea Miller”或 "John Adams" 的建议,但不会显示 "Jane Doe" 或 "Tom Masters".
有什么实现方法的提示吗?
解决方法是禁用 QCompleter 过滤并使用 QSortFilterProxyModel 进行自定义过滤:
import sys
from PySide2 import QtCore, QtWidgets
class FilterModel(QtCore.QSortFilterProxyModel):
def __init__(self, parent=None):
super().__init__(parent)
self._prefix = ""
@property
def prefix(self):
return self._prefix
@prefix.setter
def prefix(self, prefix):
self._prefix = prefix.lower()
self.invalidateFilter()
def filterAcceptsRow(self, sourceRow, sourceParent):
if not self.prefix:
return True
text = (
self.sourceModel()
.index(sourceRow, self.filterKeyColumn(), sourceParent)
.data()
)
for word in text.split():
if word.lower().startswith(self.prefix):
return True
return False
class Completer(QtWidgets.QCompleter):
def setModel(self, model):
proxy_internal_model = FilterModel(self)
proxy_internal_model.setSourceModel(model)
model.setParent(proxy_internal_model)
super().setModel(proxy_internal_model)
def splitPath(self, path):
if isinstance(self.model(), FilterModel):
self.model().prefix = path
return [""]
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QLineEdit()
texts = ["Andrea Miller", "John Adams", "Jane Doe", "Tom Masters"]
completer = Completer(w)
completer.setModel(QtCore.QStringListModel(texts, w))
w.setCompleter(completer)
w.show()
sys.exit(app.exec_())