ComboBox是填充数据模型,数据模型通常是JavaScript数组,ListModel或者是整数,但是也支持其他类型的数据模型提供的属性。
QtQuick在Qt 5.7在Controls 2.5版本给出的ComboBox,它包括一下属性:
acceptableInput : bool 此属性控制组合框是否包含可编辑文本字段中的可接受文本
count : int 组合框中的项目数
currentIndex : int 保存组合框中当前项的索引,只读
currentText : string 组合框中当前项的文本,只读
delegate : Component 包含一个委托,该委托在组合框弹出窗口中显示项目
displayText : string 保存组合框按钮上显示的文本
down : bool 保存组合框按钮是否在视觉上向下
editText : string 指示将文本保存在可编辑组合框的文本字段中
editable : bool 控制组合框是否可编辑
flat : bool 控制组合框按钮是否平坦
highlightedIndex : int 表示组合框弹出列表中突出显示项的索引,,只读
indicator : Item 包含拖放指示器项
inputMethodComposing : bool 表示可编辑组合框是否具有部分文本输入采用某种输入方法
inputMethodHints : flags 为输入法提供有关组合框的预期内容及其操作方式的提示
model : model 控制着为组合框提供数据的模型
popup : Popup 包含弹出窗口
pressed : bool 代表组合框按钮是否以物理的方式按下
textRole : string 表示用于填充组合框的模型角色
validator : Validator 包含可编辑组合框的输入文本验证程序
每次使用ComboBox时需根据自己的需求设计这些属性,而Qt给出的默认ComboBox属性样式无法满足项目需求,具体样式如下图所示:
怎么样是不是挺丑的,黑乎乎的。要使用好看满足项目需求样式的ComboBox,就需要设计delegate、indicator、contentItem、background、popup等,分别为组合框弹出窗口的委托、下拉框指向尖括号样式、显示字样栏、背景和弹出ListView样式。自定义ComboBox重写这些样式,在同一个项目中可重复使用,自定义完成后每次只需给出字体样式、大小、颜色等即可,具体的自定义控件见如下ComboBox.qml文件:
/*
* 自定义QML CheckBox
* Since:Qt 5.7 采用QtQuick.Controls 2.12库(2.0版)
*/
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Controls.impl 2.12
import QtQuick.Templates 2.12 as T
T.ComboBox {
id: control;
implicitWidth: implicitBackgroundWidth;
implicitHeight: implicitBackgroundHeight;
leftPadding: padding + (!control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing);
rightPadding: padding + (control.mirrored || !indicator || !indicator.visible ? 0 : indicator.width + spacing);
// 可在此定义多为改变的特殊属性,在调用时直接指定此属性即可
font.pointSize: 12;
font.family: "Microsoft YaHei";
property color fontColor: "#999999"; // 字体颜色
property color backgroundColor: "#E5E5E5"; // 背景色
// 弹出框行委托
delegate: ItemDelegate {
width: parent.width;
height: 30;
// 行字体样式
contentItem: Text {
text: modelData;
font: control.font;
color: control.fontColor;
elide: Text.ElideRight;
verticalAlignment: Text.AlignHCenter;
renderType: Text.NativeRendering;
}
palette.text: control.palette.text;
palette.highlightedText: control.palette.highlightedText;
font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal;
highlighted: control.highlightedIndex === index;
hoverEnabled: control.hoverEnabled;
}
// 右侧下拉箭头
indicator: Canvas {
id: canvas;
x: control.width - width - control.rightPadding;
y: control.topPadding + (control.availableHeight - height) / 2;
width: 10;
height: 6;
contextType: "2d";
Connections {
target: control;
onPressedChanged: canvas.requestPaint();
}
onPaint: {
context.reset();
context.moveTo(0, 0);
context.lineWidth = 2;
context.lineTo(width / 2, height*0.8);
context.lineTo(width, 0);
context.strokeStyle = control.pressed ? "#EEEFF7" : "#999999";
context.stroke();
}
}
// ComboBox的文字位置样式
contentItem: T.TextField {
leftPadding: !control.mirrored ? 12 : control.editable && activeFocus ? 3 : 1;
rightPadding: control.mirrored ? 12 : control.editable && activeFocus ? 3 : 1;
topPadding: 6 - control.padding;
bottomPadding: 6 - control.padding;
text: control.editable ? control.editText : control.displayText;
enabled: control.editable;
autoScroll: control.editable;
readOnly: control.down;
inputMethodHints: control.inputMethodHints;
validator: control.validator;
font: control.font;
color: control.fontColor;
//color: control.editable ? control.palette.text : control.palette.buttonText
selectionColor: control.palette.highlight;
selectedTextColor: control.palette.highlightedText;
verticalAlignment: Text.AlignVCenter;
renderType: Text.NativeRendering;
background: Rectangle {
visible: control.enabled && control.editable && !control.flat;
border.width: parent && parent.activeFocus ? 2 : 1;
border.color: parent && parent.activeFocus ? control.palette.highlight : control.palette.button;
color: control.palette.base;
}
}
// ComboBox 的背景样式
background: Rectangle {
implicitWidth: 120;
implicitHeight: 30;
radius: 3;
color: control.enabled ? "#FFFFFF" : control.backgroundColor;
border.color: control.backgroundColor;
border.width: !control.editable && control.visualFocus ? 2 : 1;
visible: !control.flat || control.down;
}
// 弹出窗口样式
popup: T.Popup {
y: control.height;
width: control.width;
//height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin);
height: contentItem.implicitHeight;
topMargin: 3;
bottomMargin: 3;
contentItem: ListView {
// 防止显示过界
clip: true;
//禁止滑动
// interactive: false;
//禁用橡皮筋效果
boundsBehavior: Flickable.StopAtBounds;
implicitHeight: contentHeight;
model: control.delegateModel;
currentIndex: control.highlightedIndex;
highlightMoveDuration: 0;
Rectangle {
z: 10;
width: parent.width;
height: parent.height;
color: "transparent";
border.color: control.palette.mid;
}
T.ScrollIndicator.vertical: ScrollIndicator { }
}
background: Rectangle {
color: control.pressed ? "#EEEFF7" : control.palette.window;
border.width: 1;
border.color: control.backgroundColor;
radius: 3;
}
}
}
在main.qml中引入两种控件qml路径as成My,并使用此Controls具体见代码实现:
import QtQuick 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.12
import "myControl" as My
Window {
visible: true;
width: 640;
height: 480;
title: qsTr("自定义Control");
My.Label {
anchors.top: parent.top;
anchors.topMargin: 56;
anchors.right: comBox1.left;
anchors.rightMargin: 15;
text: qsTr("无样式ComboBox");
}
ComboBox {
id: comBox1;
width: 150;
height: 30;
anchors.top: parent.top;
anchors.topMargin: 50;
anchors.left: parent.left;
anchors.leftMargin: 150;
model: ["测试", "bug", "开发"];
onCurrentIndexChanged: {
}
}
My.Label {
anchors.top: comBox1.bottom;
anchors.topMargin: 56;
anchors.right: comBox2.left;
anchors.rightMargin: 15;
text: qsTr("自定义ComboBox1");
}
My.ComboBox {
id: comBox2;
width: 150;
anchors.top: comBox1.bottom;
anchors.topMargin: 50;
anchors.left: parent.left;
anchors.leftMargin: 150;
fontColor: "green";
backgroundColor: "blue";
model: ["冬瓜", "白菜", "西红柿"];
onCurrentIndexChanged: {
}
}
My.Label {
anchors.top: comBox2.bottom;
anchors.topMargin: 56;
anchors.right: comBox3.left;
anchors.rightMargin: 15;
text: qsTr("自定义ComboBox2");
}
My.ComboBox {
id: comBox3;
width: 150;
anchors.top: comBox2.bottom;
anchors.topMargin: 50;
anchors.left: parent.left;
anchors.leftMargin: 150;
model: ["苹果", "橘子", "香蕉"];
onCurrentIndexChanged: {
}
}
}
展示作者定义的浅色系ComboBox,如下运行图第三个控件:
给出一些需要改变的小属性展示,如字体大小颜色,背景大小等,见下图第二个控件: