You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 13:35:29