QML自定义ComboBox组件,支持动态筛选

        QtQuick.Controls提供了ComboBox组件,该组件能够满足日常的下拉选择框的需求,但当需要用户在ComboBox中通过输入关键字进行自动匹配时,原生的组件虽然提供了editable属性用于输入关键字,但是匹配内容不弹出下拉框,无法动态筛选。自定义的ComboBox组件筛选效果:

组件新增属性:

bool filterAble : 是否动态筛选,当为false时用户无法输入且不弹出筛选框
int indicatorPadding : 下拉箭头距离右边缘
int popupHeight : 下拉框高度
color popupColor : 下拉框颜色
color textColor  : 显示字体颜色

        代码较为简单,主要是实现操作逻辑过程,完整的测试Demo如下(免积分):

QML自定义ComboBox组件Demoicon-default.png?t=N7T8https://download.csdn.net/download/zjgo007/88800367组件使用方法:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls.Material 2.3

Window {
    width: 420
    height: 260
    visible: true
    color: "#191313"
    title: qsTr("MyComboBox")

    MyComboBox{
        x:10
        y:10
        width:120
        height:40
        model:["直升机","B2","B52","F16","F22","全球鹰"]
        filterAble: true
        onCurrentTextChanged: {
            logText.text = currentText
        }
    }
    Text{
        height:40
        x:150
        y:10
        color:"ghostwhite"
        font.bold: true
        font.family: "微软雅黑"
        text:"当前选中:"
        verticalAlignment: Text.AlignVCenter
    }

    Text{
        id:logText
        x:240
        y:10
        height:40
        color:"#38d3dc"
        font.bold: true
        font.family: "微软雅黑"
        verticalAlignment: Text.AlignVCenter
    }
}

组件MyComboBox.qml代码:

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.3

ComboBox {
    id:comboBox
    width: 90
    height: 36
    leftPadding: 5
    rightPadding: 20
    property bool filterAble : false
    property int indicatorPadding:5
    property int popupHeight: 260
    property color popupColor: "#e63f3f3f"
    property color textColor : "#38d3dc"

    Material.accent: "#38d3dc"
    Material.foreground: "#38d3dc"
    Material.background: "#6638d3dc"
    font.bold: true
    font.pointSize: 9
    font.family: "微软雅黑"
    popup.font.pointSize: 9
    popup.leftPadding: 0
    popup.height: popupHeight
    popup.font.bold: true
    popup.font.family: "微软雅黑"
    popup.background: Rectangle{
        color: popupColor
    }
    contentItem: TextInput {
        id:contentText
        clip: true
        text: comboBox.displayText
        font: comboBox.font
        color: textColor
        verticalAlignment: Text.AlignVCenter
        selectByMouse: true
        readOnly: !filterAble
        onTextEdited:{
            dataFilter(text)
        }
    }
    indicator: Canvas {
        id: canvas
        x: comboBox.width - width - indicatorPadding
        y: comboBox.topPadding + (comboBox.availableHeight - height) / 2
        width: 8
        height: 6
        contextType: "2d"

        Connections {
            target: comboBox
            function onPressedChanged() { canvas.requestPaint(); }
        }

        onPaint: {
            context.reset();
            context.moveTo(0, 0);
            context.lineTo(width, 0);
            context.lineTo(width / 2, height);
            context.closePath();
            context.fillStyle = textColor;
            context.fill();
        }
    }
    onCurrentTextChanged: {
        contentText.text = currentText
    }


    Popup {
        id: popupFilter
        width: parent.width
        height: popupHeight
        y:parent.height
        background: Rectangle{
            color: popupColor
        }

        contentItem: ListView {
            id: filterListView

            anchors.fill: parent
            clip: true
            highlight: Rectangle {color: "#6638d3dc"; radius: 5 }
            delegate: Item{
                width: popupFilter.width
                height: 30
                clip: true
                Row{
                    anchors.fill: parent
                    anchors.left: parent.left
                    anchors.leftMargin: 10
                    anchors.right:parent.right
                    anchors.rightMargin: 10
                    spacing: 10
                    Text {
                        height:30
                        text: modelData
                        anchors.verticalCenter: parent.verticalCenter
                        font.family: "微软雅黑"
                        font.pixelSize: 13
                        verticalAlignment: Text.AlignVCenter
                        color: "ghostwhite"
                        font.bold: true
                    }
                }



                MouseArea{
                    anchors.fill: parent
                    hoverEnabled: true
                    onEntered: {
                        filterListView.currentIndex = index
                    }

                    onClicked: {
                        var index = comboBox.find(modelData)
                        currentIndex = index
                        popupFilter.close()
                    }
                }
            }
        }
    }

    function dataFilter(filter){
        popupFilter.open()
        var filterList = []
        for(var i in comboBox.model){
            var modelData = comboBox.model[i]
            if(String(modelData).indexOf(filter) != -1){
                filterList.push(modelData)
            }
        }
        filterListView.model = filterList
    }
}

相关推荐

  1. 【Vue3】定义Input

    2024-02-06 20:46:01       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-06 20:46:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-06 20:46:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-06 20:46:01       82 阅读
  4. Python语言-面向对象

    2024-02-06 20:46:01       91 阅读

热门阅读

  1. C#面:.NET Remoting 的工作原理是什么

    2024-02-06 20:46:01       52 阅读
  2. (三)相机的分类与选型

    2024-02-06 20:46:01       60 阅读
  3. Excel文件按照列内容进行分组

    2024-02-06 20:46:01       45 阅读
  4. Linux前后端程序部署

    2024-02-06 20:46:01       41 阅读
  5. 假期2.5

    2024-02-06 20:46:01       49 阅读
  6. 设计模式(结构型模式)适配器模式

    2024-02-06 20:46:01       50 阅读
  7. ChatGPT 和文心一言哪个更好用?

    2024-02-06 20:46:01       51 阅读