在Qt 6.8的QML+Python项目中基于QSortFilterProxyModel实现TableModel过滤并关联搜索栏
在Qt 6.8的QML+Python项目中基于QSortFilterProxyModel实现TableModel过滤并关联搜索栏
我刚好做过类似的需求,给你一步步拆解怎么修改代码实现。核心思路是用QSortFilterProxyModel作为源模型和QML TableView之间的中间层,把搜索栏的输入直接绑定到代理模型的过滤属性上,这样就能实时过滤数据了。
第一步:修改main.py,添加源模型和代理模型
首先我们得先有一个带数据的源模型,再用QSortFilterProxyModel做中间层,最后把代理模型暴露给QML让它能访问到。我用QStandardItemModel做示例(你也可以换成自定义的QAbstractTableModel),修改后的完整main.py如下:
import sys from pathlib import Path from PySide6.QtCore import ( QtMsgType, qInstallMessageHandler, QSortFilterProxyModel, QStandardItemModel, QStandardItem, Qt ) from PySide6.QtGui import QGuiApplication from PySide6.QtQml import QQmlApplicationEngine def handle_qml_message(msg_type, context, message): print(f"QML: {message}") # 自定义代理模型(可选,用于多列过滤) class MultiColumnSortFilterProxyModel(QSortFilterProxyModel): def filterAcceptsRow(self, source_row, source_parent): source_model = self.sourceModel() # 遍历所有列,检查是否有列包含过滤文本(不区分大小写) filter_text = self.filterFixedString().lower() for column in range(source_model.columnCount()): index = source_model.index(source_row, column, source_parent) data = source_model.data(index, self.filterRole()) if data and filter_text in str(data).lower(): return True return False if __name__ == "__main__": qInstallMessageHandler(handle_qml_message) app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() # 1. 创建源数据模型并填充测试数据 source_model = QStandardItemModel() source_model.setHorizontalHeaderLabels(["ID", "姓名", "邮箱"]) test_data = [ (1, "张三", "zhangsan@example.com"), (2, "李四", "lisi@example.com"), (3, "王五", "wangwu@example.com"), (4, "赵六", "zhaoliu@example.com"), (5, "张小明", "zhangxiaoming@example.com") ] for row_data in test_data: items = [QStandardItem(str(item)) for item in row_data] source_model.appendRow(items) # 2. 实例化代理模型并配置 # 如果你只需要单列过滤,用默认的QSortFilterProxyModel就行: # proxy_model = QSortFilterProxyModel() # proxy_model.setFilterKeyColumn(0) # 只过滤第一列(ID列) # 用自定义的多列过滤模型 proxy_model = MultiColumnSortFilterProxyModel() proxy_model.setSourceModel(source_model) proxy_model.setFilterRole(Qt.DisplayRole) # 基于显示文本过滤 # 3. 把代理模型暴露给QML,命名为"proxyModel" engine.rootContext().setContextProperty("proxyModel", proxy_model) qml_file = Path(__file__).resolve().parent / "main.qml" engine.load(qml_file) if not engine.rootObjects(): sys.exit(-1) sys.exit(app.exec())
第二步:修改main.qml,添加搜索栏并绑定过滤
接下来在QML里添加搜索输入框,把它的文本和代理模型的过滤属性绑定,同时把TableView的模型换成代理模型:
import QtQuick 6.8 import QtQuick.Controls 6.8 import QtQuick.Layouts 6.8 Window { width: 600 height: 400 visible: true title: qsTr("搜索过滤表格") ColumnLayout { anchors.fill: parent anchors.margins: 10 spacing: 10 // 搜索栏:输入文本实时同步到代理模型的过滤条件 TextField { Layout.fillWidth: true placeholderText: qsTr("输入关键词搜索...") // 双向绑定,输入文本自动更新过滤规则 text: proxyModel.filterFixedString onTextChanged: proxyModel.filterFixedString = text } // 表格视图:使用代理模型作为数据源 TableView { Layout.fillWidth: true Layout.fillHeight: true model: proxyModel // 定义表格列,对应源模型的列 TableViewColumn { role: "display" title: qsTr("ID") width: 100 } TableViewColumn { role: "display" title: qsTr("姓名") width: 150 } TableViewColumn { role: "display" title: qsTr("邮箱") width: 300 } } } }
额外小技巧
- 如果需要支持正则表达式搜索,只需要把QML里的
filterFixedString换成filterRegularExpression就行,比如把TextField的绑定改成:text: proxyModel.filterRegularExpression.pattern onTextChanged: proxyModel.filterRegularExpression = text - 如果你用的是自定义
QAbstractTableModel,记得要在模型里重写roleNames()方法,把自定义角色暴露给QML,然后代理模型的filterRole要设置成对应的角色值,比如你的模型有NameRole,就设置proxy_model.setFilterRole(YourModel.NameRole)
备注:内容来源于stack exchange,提问作者mayadev
相关产品推荐
相关产品推荐

