这是一个默认的ComboBox
的样子(Win10上测试结果):
代码很简单,如下所示:
ComboBox {
id: control
width: 200
height: 32
model: [qsTr("Fade in"), qsTr("Fade out"), qsTr("Slide")]
}
其中model
是为ComboBox
提供数据。
ComboBox
主要分成两个部分:
ComboBox
可以定制的东西有:背景、内容、指示器以及每一个单项的代理,定制框架如下:
ComboBox {
delegate: ItemDelegate {
}
indicator: Image {
}
contentItem: Text {
}
background: Rectangle {
}
}
我们想要更换默认的指示器[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传要如何操作呢?
我们需要改变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"
}
那么我们想要改变它的背景的话如何操作呢?
我们需要改变ComboBox
默认的background
样式。我们可以将background
样式改为一个Rectangle
,然后修改这个Rectangle
的颜色即可。
ComboBox {
...
background: Rectangle {
implicitWidth: 120
implicitHeight: 40
color: "red"
border.color: "#464546"
border.width: 1
radius: 2
}
}
效果如上,它改变的背景是ComboBox
主体框架的背景颜色,如果需要改变弹出框中每一个项的背景颜色,这时需要定制delegate
代理,可以查看代理定制一节。
如果想改变文本的一些属性的话,我们可以改变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
}
正常未点击的状态:
点击时文本颜色改变为红色 (背景修改为白色)。
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
中的contentHeight
是Popup
的成员,表示弹框的隐式高度。
另外,最重要的是我们要定制它的代理,即:model: control.popup.visible ? control.delegateModel : null
,详见下一节。
对于每一项的定制,需要实现一个delegate : Component
。代理的组件,官方推荐使用ItemDelegate
或任何其他继承于AbstractButton
的类型作为代理,这一点是为了确保弹框能够正常的交互工作以及自动关闭,如果使用其他类型作为代理组件,那么一定需要自己关闭弹框。在此我们使用官方推荐的ItemDelegate
作为代理。
ItemDelegate
同样的有contentItem
、background
,因为它继承自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
是一个图片按钮,跟按钮的属性基本一致,只是多了一个图片,可以参考这骗文章:。
整个效果如下:
处理下拉选项卡的点击事件。
可以在delegate: ItemDelegate
中处理,ItemDelegate
有一个clicked
的信号,来处理点击事件,然后使用index
来表示点击的是第几个选项。
定制一个点击弹框项右侧的“-”减号图标,将实时删掉一项。这个需要执行两个步骤:
将model
项改用ListModel
实现(因为ListModel
有增删的接口)
ListModel {
id: listModel
ListElement { modelData: qsTr("Fade in") }
ListElement { modelData: qsTr("Fade out") }
ListElement { modelData: qsTr("Slide") }
}
将ComboBox
的model
项改为: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”,获取资源链接。有任何疑问也可以公众号里留言咨询。