QtQuick.Controls提供了ComboBox组件,该组件能够满足日常的下拉选择框的需求,但当需要用户在ComboBox中通过输入关键字进行自动匹配时,原生的组件虽然提供了editable属性用于输入关键字,但是匹配内容不弹出下拉框,无法动态筛选。自定义的ComboBox组件筛选效果:
组件新增属性:
bool filterAble : 是否动态筛选,当为false时用户无法输入且不弹出筛选框
int indicatorPadding : 下拉箭头距离右边缘
int popupHeight : 下拉框高度
color popupColor : 下拉框颜色
color textColor : 显示字体颜色
代码较为简单,主要是实现操作逻辑过程,完整的测试Demo如下(免积分):
QML自定义ComboBox组件Demohttps://download.csdn.net/download/zjgo007/88800367组件使用方法:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls.Material 2.3Window {width: 420height: 260visible: truecolor: "#191313"title: qsTr("MyComboBox")MyComboBox{x:10y:10width:120height:40model:["直升机","B2","B52","F16","F22","全球鹰"]filterAble: trueonCurrentTextChanged: {logText.text = currentText}}Text{height:40x:150y:10color:"ghostwhite"font.bold: truefont.family: "微软雅黑"text:"当前选中:"verticalAlignment: Text.AlignVCenter}Text{id:logTextx:240y:10height:40color:"#38d3dc"font.bold: truefont.family: "微软雅黑"verticalAlignment: Text.AlignVCenter}
}
组件MyComboBox.qml代码:
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.3ComboBox {id:comboBoxwidth: 90height: 36leftPadding: 5rightPadding: 20property bool filterAble : falseproperty int indicatorPadding:5property int popupHeight: 260property color popupColor: "#e63f3f3f"property color textColor : "#38d3dc"Material.accent: "#38d3dc"Material.foreground: "#38d3dc"Material.background: "#6638d3dc"font.bold: truefont.pointSize: 9font.family: "微软雅黑"popup.font.pointSize: 9popup.leftPadding: 0popup.height: popupHeightpopup.font.bold: truepopup.font.family: "微软雅黑"popup.background: Rectangle{color: popupColor}contentItem: TextInput {id:contentTextclip: truetext: comboBox.displayTextfont: comboBox.fontcolor: textColorverticalAlignment: Text.AlignVCenterselectByMouse: truereadOnly: !filterAbleonTextEdited:{dataFilter(text)}}indicator: Canvas {id: canvasx: comboBox.width - width - indicatorPaddingy: comboBox.topPadding + (comboBox.availableHeight - height) / 2width: 8height: 6contextType: "2d"Connections {target: comboBoxfunction 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: popupFilterwidth: parent.widthheight: popupHeighty:parent.heightbackground: Rectangle{color: popupColor}contentItem: ListView {id: filterListViewanchors.fill: parentclip: truehighlight: Rectangle {color: "#6638d3dc"; radius: 5 }delegate: Item{width: popupFilter.widthheight: 30clip: trueRow{anchors.fill: parentanchors.left: parent.leftanchors.leftMargin: 10anchors.right:parent.rightanchors.rightMargin: 10spacing: 10Text {height:30text: modelDataanchors.verticalCenter: parent.verticalCenterfont.family: "微软雅黑"font.pixelSize: 13verticalAlignment: Text.AlignVCentercolor: "ghostwhite"font.bold: true}}MouseArea{anchors.fill: parenthoverEnabled: trueonEntered: {filterListView.currentIndex = index}onClicked: {var index = comboBox.find(modelData)currentIndex = indexpopupFilter.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}
}