Qml控件:ComboBox

请添加图片描述
更多资讯、知识,微信公众号搜索:“上官宏竹”。


ComboBox默认状态

这是一个默认的ComboBox的样子(Win10上测试结果):

代码很简单,如下所示:

ComboBox {
	id: control
	width: 200
	height: 32
	model: [qsTr("Fade in"), qsTr("Fade out"), qsTr("Slide")]
}

其中model是为ComboBox提供数据。

ComboBox主要分成两个部分:

  • 一个是显示的区域
  • 一个是一个Popup的弹框,如下:

定制ComboBox

1、定制框架

ComboBox可以定制的东西有:背景、内容、指示器以及每一个单项的代理,定制框架如下:

ComboBox {
    delegate: ItemDelegate {
    }

    indicator: Image {
    }

    contentItem: Text {
    }

    background: Rectangle {
    }
}

2、定制指示器

我们想要更换默认的指示器[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HxInvtyg-1653562293938)(C:\Users\xuan.tan\AppData\Roaming\Typora\typora-user-images\image-20220519202529517.png)]要如何操作呢?

我们需要改变ComboBox默认的indicator样式。如果是一张图片,那么我们可以将indicator样式改为一个Image即可。

indicator: Image {
	x: control.width - width - control.rightPadding
	y: control.topPadding + (control.availableHeight - height) / 2
	width: 16
	height: 16
	source: "qrc:/combox_indicator"
}

3、定制背景

那么我们想要改变它的背景的话如何操作呢?

我们需要改变ComboBox默认的background样式。我们可以将background样式改为一个Rectangle,然后修改这个Rectangle的颜色即可。

ComboBox {
	...
	background: Rectangle {
		implicitWidth: 120
		implicitHeight: 40
		color: "red"
		border.color: "#464546"
		border.width: 1
		radius: 2
	}
}

效果如上,它改变的背景是ComboBox主体框架的背景颜色,如果需要改变弹出框中每一个项的背景颜色,这时需要定制delegate代理,可以查看代理定制一节。

4、定制内容

如果想改变文本的一些属性的话,我们可以改变ComboBox默认的contentItem的样式。contentItem可以使用继承于 Item的类型进行重新定义。
我们当前可以使用一个Text来定制文本的颜色、字体等信息,更复杂的需求可以使用Rectangle等其他的类型进行重新定义。

contentItem: Text {
	leftPadding: 12
	rightPadding: control.indicator.width + control.spacing
	topPadding: 5
	bottomPadding: 5

	text: control.displayText
	font.pixelSize: 18
	font.bold: true
	color: control.pressed ? "red" : "green"
	verticalAlignment: Text.AlignVCenter
	elide: Text.ElideRight
}

正常未点击的状态:
点击时文本颜色改变为红色 (背景修改为白色)。

5、定制弹框

popup的弹框可以使用Popup类型去定义,但它不能使用其他类型定义,毕竟这是一个弹框,不可以用Rectangle等去定义它。

既然是Popup类型,那么它也有它的背景属性background,这个和上述的定制背景可以做一样的操作。

另外在ComboBox中,对于Popup来说,最重要的是要定制它弹出的内容,及contentItem。这里一般都是使用一个ListView去定制,因为你的数据是一个数组,并且更有可能是一个动态数组(可以支持增删改等操作)。

我们定制Popup的基本框架如下,背景的定制和上述一样。这里重点讨论对contentItem的定制。

popup: Popup {
	contentItem: ListView {
	}

	background: Rectangle {
	}
}

对于ListView,一般写法如下:

contentItem: ListView {
	clip: true
	implicitHeight: contentHeight
	model: control.popup.visible ? control.delegateModel : null
	currentIndex: control.highlightedIndex

	ScrollIndicator.vertical: ScrollIndicator { }
}

implicitHeight: contentHeight中的contentHeightPopup的成员,表示弹框的隐式高度。

另外,最重要的是我们要定制它的代理,即:model: control.popup.visible ? control.delegateModel : null,详见下一节。

6、定制弹框Item

对于每一项的定制,需要实现一个delegate : Component。代理的组件,官方推荐使用ItemDelegate或任何其他继承于AbstractButton的类型作为代理,这一点是为了确保弹框能够正常的交互工作以及自动关闭,如果使用其他类型作为代理组件,那么一定需要自己关闭弹框。在此我们使用官方推荐的ItemDelegate作为代理。

ItemDelegate同样的有contentItembackground,因为它继承自Control。对于每项的背景色的定制,通上述的定制背景一样,使用一个Rectangle来完成。对于contentItem的定制,我们可以增加许多内容,比如由两个部分组成:文本+图片,文本靠左,图片靠右,那么格式如下:

contentItem: Item {
	anchors.fill: parent

	Text {

	}
	ImageButton {

	}
}

Text按照正常的定义如下:

Text {
	anchors.left: parent.left
	anchors.leftMargin: 11
	anchors.top: parent.top
	anchors.topMargin: 4
	anchors.bottom: parent.bottom
	anchors.bottomMargin: 4

	text: modelData
	color: "#FFFFFF"
	font: control.font
	elide: Text.ElideRight
	verticalAlignment: Text.AlignVCenter
}

主要是定义它的锚点及文本大小、颜色等属性。这里说一下text: modelData,这里指的是ComboBox属性model中的数据部分,是一个内置变量。

ImageButton是一个图片按钮,跟按钮的属性基本一致,只是多了一个图片,可以参考这骗文章:。

整个效果如下:

7、弹框项的点击

处理下拉选项卡的点击事件。

可以在delegate: ItemDelegate中处理,ItemDelegate有一个clicked的信号,来处理点击事件,然后使用index来表示点击的是第几个选项。

8、定制删除项动作

定制一个点击弹框项右侧的“-”减号图标,将实时删掉一项。这个需要执行两个步骤:

  • model项改用ListModel实现(因为ListModel有增删的接口)

    ListModel {
    	id: listModel
    	ListElement { modelData: qsTr("Fade in") }
    	ListElement { modelData: qsTr("Fade out") }
    	ListElement { modelData: qsTr("Slide") }
    }
    

    ComboBoxmodel项改为:model: listModel

  • 实现ImageButton的点击事件

    定义一个信号,并在ImageButton的点击事件onBtnClicked将其触发(ImageButton的具体实现可以参考:自定义Qml控件:ImageButton 一章),代码格式如下:

    signal itemMinus(int index)
    
    ImageButton {
    	onBtnClicked: {
    		itemMinus(index)
    	}
    }
    

    外部实现itemMinus这个信号的槽函数onItemMinus,在这个槽函数中将model的项删除一个即可。

效果如下:

请添加图片描述

如果想要每一个弹出项都不一致,可以对model,增加几个属性,在弹框的contentItem: Item中进行定制化修改。比如,如果想控制某个弹出项是否显示删除按钮,可以将ListModel增加一个域,如下定义:

ListModel {
	id: listModel
	ListElement { modelData: qsTr("Fade in"); minus: false }
	ListElement { modelData: qsTr("Fade out"); minus: ture }
	ListElement { modelData: qsTr("Slide"); minus: ture }
}

ComboBox内部通过model.minus变量来判定ImageButton的显示与否。


完整实现可以微信搜索公众号:“上官宏竹”,或者扫下面的二维码,关注并回复:“ComboBox”,获取资源链接。有任何疑问也可以公众号里留言咨询。


更多资讯、知识,微信公众号搜索:“上官宏竹”。
请添加图片描述

  • 15
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值