You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何在QML中使用CheckBox过滤ListView?

QML实现ListView多条件过滤(TextField+CheckBox)

我在QML中基于以下JSON数据生成了ListView,目前已实现通过TextField对PinName字段进行过滤,现在需要额外添加用CheckBoxMake字段的过滤功能。

{
    "Toyota" :
    [
        { 
            "Make": "RAV4",    
            "PinName": "J1-A3/A4", 
            "PinType": "Digital",  
            "PinDirection": "Output", 
            "Function Name": "Reverse Output" 
        },
        { 
            "Make": "RAV4",    
            "PinName":"J1-C1",
            "PinType": "Analogue",
            "PinDirection": "Input",  
            "Function Name": "Fuel Sensor Signal" 
        },
        { 
            "Make": "Fortuner",
            "PinName": "J1-C2",    
            "PinType": "Tristate", 
            "PinDirection": "Input",  
            "Function Name": "Generic Spare" 
        },
        { 
            "Make": "Fortuner",
            "PinName": "J1-C3/C4", 
            "PinType": "Digital",  
            "PinDirection": "Output", 
            "Function Name": "Bin Marker Lights" 
        },
        {
            "Make": "Corolla", 
            "PinName": "J1-D1",    
            "PinType": "Tristate", 
            "PinDirection": "Input",  
            "Function Name": "DiffLock Switch (CTD)" 
        },
        { 
            "Make": "Corolla", 
            "PinName": "J1-D2",    
            "PinType": "Tristate", 
            "PinDirection": "Output", 
            "Function Name": "Park Brake Press Switch" 
        }
    ],

    "Volkswagen":
    [
        { 
            "Make": "Polo",   
            "PinName": "J1-A3/A4", 
            "PinType": "Digital",  
            "PinDirection": "Output", 
            "Function Name": "Reverse Output" 
        },
        { 
            "Make": "Polo",   
            "PinName": "J1-C1",    
            "PinType": "Analogue", 
            "PinDirection": "Input",  
            "Function Name": "Fuel Sensor Signal" 
        },
        { 
            "Make": "Taigo",  
            "PinName": "J1-C2",    
            "PinType": "Tristate", 
            "PinDirection": "Input",  
            "Function Name": "Generic Spare" 
        },
        { 
            "Make": "Taigo",  
            "PinName": "J1-C3/C4", 
            "PinType": "Digital",  
            "PinDirection": "Output", 
            "Function Name": "Bin Marker Lights" 
        },
        { 
            "Make": "Tiguan", 
            "PinName": "J1-D1",    
            "PinType": "Tristate", 
            "PinDirection": "Input",  
            "Function Name": "DiffLock Switch (CTD)" 
        },
        { 
            "Make": "Tiguan", 
            "PinName": "J1-D2",    
            "PinType": "Tristate", 
            "PinDirection": "Output", 
            "Function Name": "Park Brake Press Switch" 
        }
    ] 
}

我当前实现的ListView代码如下:

ListView {
        id: pinListView
        Layout.fillWidth: true
        Layout.fillHeight: true
        clip: true
        model: FilterDelegateModel {
            id: filterDelegateModel
            model: pinModel
            filter: search ? function(model){
                var isFound = false ;
                var i = 0 ;
                //===================================================

                const pattern = search.trim() ;
                if(pattern.length > 0){
                    var regex = new RegExp(pattern,'i' /*ignore case*/);  //What does this do????

                    isFound = (regex.test(model.Make+ model.FunctionName )) ;
                }

                return isFound ;
            } : null
            property string search: searchTextEdit.text.trim().toLowerCase()
            onSearchChanged: Qt.callLater(update)
            delegate: Frame {
                id: frame
                property int visibleIndex: DelegateModel.visibleIndex
                width: ListView.view.width
                background: Rectangle {
                    color: visibleIndex & 1 ? "#404040" : "#343434"
                    border.color: "#7D7D7D"
                    border.width: 1
                }
                RowLayout {
                    id: layout
                    anchors.fill: parent
                    spacing: 6
                    Text {
                        text: (visibleIndex + 1)
                        color: "#fdbb30"
                        font.bold: true
                        font.pointSize: 9
                    }
                    Text {
                        Layout.fillWidth: true
                        text: model.functionName+" - "+"["+model.make+"]"
                        color: "white" //"#fdbb30"
                        font.bold: true
                        font.pointSize: 9
                    }

                    Rectangle {
                        color: 'transparent'//'transparent'//'plum'
                        Layout.alignment: Qt.AlignLeft
                        //Layout.fillWidth: true
                        Layout.minimumWidth: 50
                        Layout.preferredWidth: layout.width*0.5
                        Layout.maximumWidth: layout.width*0.5
                        Layout.minimumHeight: 40

                        Loader {
                            id: controlLoader
                         //   sourceComponent: pinListView.getPinControl(model.direction, model.type)
                            anchors.centerIn: parent
                        }
                    }
                } //RowLayout
            }//Frame
        }//FilterDelegateModel
    } //ListView

实现步骤

  1. 提取唯一Make值并生成CheckBox组
    从JSON数据中提取所有不重复的Make名称,动态生成对应的CheckBox供用户选择过滤车型。

  2. 维护选中的Make集合
    创建列表存储用户选中的Make值,CheckBox状态变化时同步更新该集合。

  3. 修改过滤逻辑
    在原有TextField过滤基础上,加入CheckBox的选中条件:若选中特定Make则只显示对应条目;若未选中任何CheckBox则不对Make做过滤。

修改后的完整代码

// 顶部添加CheckBox过滤栏
RowLayout {
    id: makeFilterLayout
    Layout.fillWidth: true
    spacing: 10
    padding: 5

    // 提取所有唯一的Make值
    property var uniqueMakes: (function() {
        var makes = [];
        for (var brand in pinModel) {
            pinModel[brand].forEach(item => {
                if (!makes.includes(item.Make)) {
                    makes.push(item.Make);
                }
            });
        }
        return makes;
    })()

    // 存储选中的Make值
    property var selectedMakes: []

    // 动态生成CheckBox
    Repeater {
        model: makeFilterLayout.uniqueMakes
        delegate: CheckBox {
            text: modelData
            checked: true // 默认全选
            onCheckedChanged: {
                if (checked) {
                    if (!makeFilterLayout.selectedMakes.includes(modelData)) {
                        makeFilterLayout.selectedMakes.push(modelData);
                    }
                } else {
                    const index = makeFilterLayout.selectedMakes.indexOf(modelData);
                    if (index !== -1) {
                        makeFilterLayout.selectedMakes.splice(index, 1);
                    }
                }
                filterDelegateModel.update();
            }
        }
    }
}

// 修改后的ListView及过滤逻辑
ListView {
    id: pinListView
    Layout.fillWidth: true
    Layout.fillHeight: true
    clip: true
    model: FilterDelegateModel {
        id: filterDelegateModel
        model: pinModel
        filter: function(model) {
            // 1. TextField搜索过滤(针对PinName)
            let matchesSearch = true;
            const pattern = search.trim();
            if (pattern.length > 0) {
                const regex = new RegExp(pattern, 'i'); // 'i'表示忽略大小写
                matchesSearch = regex.test(model.PinName);
            }

            // 2. CheckBox的Make过滤
            let matchesMake = true;
            if (makeFilterLayout.selectedMakes.length > 0) {
                matchesMake = makeFilterLayout.selectedMakes.includes(model.Make);
            }

            // 需同时满足两个过滤条件
            return matchesSearch && matchesMake;
        }
        property string search: searchTextEdit.text.trim().toLowerCase()
        onSearchChanged: Qt.callLater(update)
        delegate: Frame {
            id: frame
            property int visibleIndex: DelegateModel.visibleIndex
            width: ListView.view.width
            background: Rectangle {
                color: visibleIndex & 1 ? "#404040" : "#343434"
                border.color: "#7D7D7D"
                border.width: 1
            }
            RowLayout {
                id: layout
                anchors.fill: parent
                spacing: 6
                Text {
                    text: (visibleIndex + 1)
                    color: "#fdbb30"
                    font.bold: true
                    font.pointSize: 9
                }
                Text {
                    Layout.fillWidth: true
                    text: model["Function Name"]+" - "+"["+model.Make+"]"
                    color: "white"
                    font.bold: true
                    font.pointSize: 9
                }

                Rectangle {
                    color: 'transparent'
                    Layout.alignment: Qt.AlignLeft
                    Layout.minimumWidth: 50
                    Layout.preferredWidth: layout.width*0.5
                    Layout.maximumWidth: layout.width*0.5
                    Layout.minimumHeight: 40

                    Loader {
                        id: controlLoader
                     //   sourceComponent: pinListView.getPinControl(model.PinDirection, model.PinType)
                        anchors.centerIn: parent
                    }
                }
            } //RowLayout
        }//Frame
    }//FilterDelegateModel
} //ListView

关键修正说明

  • 原代码过滤逻辑误写为model.Make+ model.FunctionName,已修正为针对PinName的过滤,符合需求描述。
  • 修复了JSON字段名Function Name(带空格)的读取问题,改为model["Function Name"]
  • CheckBox默认全选,用户可自由取消不需要的车型选项,状态变化时自动触发过滤更新。

内容的提问来源于stack exchange,提问作者Clive N

火山引擎 最新活动