使用 QSortFilterProxyModel,配合文本输入框的 onTextChanged 信号,实现输入自动匹配模糊查询
如果是后端查询接口实现,每次 text change 都触发数据库 like 语句查询,性能可能有问题
实现代理类
class ControlProxyModel(QSortFilterProxyModel):
def __init__(self):
super().__init__()
# 设置大小写不敏感
self.setFilterCaseSensitivity(Qt.CaseInsensitive)
# 设置原始数据模型 control_inst_model类型是QAbstractTableModel
self.setSourceModel(control_inst_model)
# 设置默认查询字段为第一列
self.setFilterKeyColumn(0)
@Slot(int)
def set_filter_role(self, index):
if 0 <= index < 4:
self.setFilterKeyColumn(index)
复制代码
通过设置 filterRole 来切换查询的列,获取 filterKeyColumn,发现没有生效
因此直接通过指定查询列 setFilterKeyColumn 来切换
实例化代理类
control_proxy_model = ControlProxyModel()
复制代码
注册代理类
engine = QQmlApplicationEngine()
engine.rootContext().setContextProperty("controlProxyModel", control_proxy_model)
复制代码
qml 里 TableView 的 model 设定为 controlProxyModel,或者在 TextField 的 onTextChanged,ComboBox 的 onCurrentIndexChanged 指定 TableView.model = controlProxyModel,都可以
// qml
// 自定义的ComboBox
CusComboBox {
id: instSearchCombo
model: ListModel {
ListElement { text: "条码" }
ListElement { text: "批号" }
ListElement { text: "名称" }
ListElement { text: "类型" }
}
onCurrentIndexChanged: {
controlProxyModel.set_filter_role(instSearchCombo.currentIndex);
}
}
复制代码
设置查询文本
TextField {
id: reagentSearchText
selectByMouse: true
placeholderText: qsTr("输入查询文本:")
onTextChanged: {
reagentProxyModel.setFilterFixedString(reagentSearchText.text);
}
}
复制代码
这样已经实现按不同的列模糊查询了
还有一个问题,按输入过滤后的行号 row,和原始的 control_inst_model 里的行号是不对应的,需要 mapToSource,把代理类行号转换为原始数据的行号
// qml
let idx = controlProxyModel.index(row, column);
let real_row = controlProxyModel.mapToSource(idx);
// real_row 是QModelIndex类
control_table_view.selectedRow = real_row.row;
复制代码
数据展示中,选中的行号是原始数据行号时,用 mapFromSource 转换成代理类的行号
// qml
controlProxyModel.mapFromSource(controlInstModel.index(control_table_view.selectedRow, 0)).row
复制代码
默认只要文本匹配,就会返回该行,如果需要自定义过滤行为,可以重新实现 filterAcceptsRow
The default implementation returns true
if the value held by the relevant item matches the filter string, wildcard string or regular expression
例如实现多列的联合查询
def setFilterText(self, t0, t1):
self.text_0 = t0
self.text_1 = t1
def filterAcceptsRow(self, sourceRow, sourceParent):
index0 = self.sourceModel().index(sourceRow, 0, sourceParent)
index1 = self.sourceModel().index(sourceRow, 1, sourceParent)
return str(self.sourceModel().data(index0)).__contains__(self.text_0 ) & str(self.sourceModel().data(index1)).__contains__(self.text_1)
复制代码
官方文档:https://doc.qt.io/qt-6/qsortfilterproxymodel.html#filterCaseSensitivity-prop
官方示例:https://doc.qt.io/qt-6/qtwidgets-itemviews-customsortfiltermodel-example.html
c++版本:https://blog.51cto.com/u_15310543/3163910
c++多列联合过滤:https://blog.csdn.net/qq78442761/article/details/84875123
评论