Qt Quick 常用元素:ComboBox(下拉列表) 与 ProgressBar(进度条)

1、ComboBox

ComboBox,即下拉列表框,由一个列表框和一个标签控件(或编辑控件)组成。ComboBox 的下拉列表是使用 Menu 实现的,列表内的每个条目对应一个 Menultem。

  • 弹出下拉列表框后,用户选择列表中的一个条目,此时 currentlndex、currentText 属性就会变化,同时 activated 信号也会发射。
  • ComboBox 的 find() 方法用于查找列表中是否存在指定的字符串,对于可编辑的 ComboBox,向列表中添加条目时可以使用此方法来滤重;textAt() 返回指定索引位置的字符串;selectAll() 可以选中可编辑 ComboBox 的编辑框内的所有文本。
  • count 属性返回ComboBox下拉列表内的条目个数。
  • 下拉列表的数据从 model 属性来。model 可以是一个简单的字符串列表,如 ["TV”,"CD Player”,"Set Top Box" , ’’Router"];也可以是 ListModel,当使用 ListModel 时,可以通过 textRole 属性指定列表条目对应的 model 内的 role,如果不设定, 则默认使用第一个 role。比如下面的 ComboBox 示例使用的 ListModel,内部数据有 text 和 color 两个角色,如果不设定 ComboBox 的 textRole,则会默认使用 model 的 text;如果设定 textRole: "color",则使用 model 的 color 角色。
ComboBox { 	editable: true;     model: ListModel { 		ListElement { text: "Banana"; color: "Yellow" } 	} 	textRole: "color"; } 
  • 你可以给 style 属性指定一个 ComboBoxStyle 对象来定制 ComboBox。其实在 ComboBox.qml 中,为 style 指定了 一个动态创建的 ComboBoxStyle 对象,看源码:style: Qt.createComponent(Settings.style + "/ComboBoxStyle.qml", comboBox)

如果你想了解怎样实现一个功能完备的 ComboBoxStyle,可以循着这个线索找到可参考的源码。为了展示 Qt Quick “一切风格皆可定制” 的特色,我们还是来看看 ComboBoxStyle 到底能干什么。

1.1 ComboBoxStyle

先说一 下ComboBox 顶部显示当前条目的那个控件。当 ComboBox 不可编辑时,它是一个 Button,显示 currentText,响应点击弹出下拉列表框。如果你还记得 ButtonStyle 这个对象,应该能够想到这个 Button 的 background 和 label 可以定制。没错,ComboBoxStyle 恰恰有 background 和 label 两个类型为 Component 的属性,就是用来定制背景和文本的。

当 ComboBox 可编辑时,一个 Textlnput 对象叠加到 Button 上面,Textlnput 左边与 Button 左边对齐,右边留一些位置给那个代表 “下拉” 含义的小图标—这个小图标的宽度由 ComboBoxStyle 的 dropDownButtonWidth 属性来决定。

好啦,现在说到了 ComboBoxStyle 的 background、label、dropDownButtonWidth 三个属性。control 指向 ComboBox 实例,而 renderType —般不用设置。

QT开发交流+赀料君羊:714620761

1.2 ComboBox 综合演示

combobox demo.qml 的内容如下:

import QtQuick 2.2 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2  Rectangle {     width: 480;     height: 360;     color: "#a0b0a0";      Grid {         anchors.fill: parent;         rows: 2;         columns: 2;         rowSpacing: 4;         columnSpacing: 4;         GroupBox {             width: 200;             height: 120;             title: "只读电器";             ComboBox {                 anchors.top: parent.top;                 anchors.topMargin: 8;                 width: parent.width;                 model: ["TV" , "CD Player" , "Set Top Box" , "Router"];             }         }          GroupBox {             width: 200;             height: 120;             title: "可编辑水果";             ComboBox {                 anchors.top: parent.top;                 anchors.topMargin: 8;                 width: parent.width;                 editable: true;                 model: ListModel {                     ListElement { text: "Banana"; color: "Yellow" }                 }                 //textRole: "color";                 onAccepted: {                     if(count < 4 && find(currentText) === -1){                         model.append({text: editText});                         currentIndex = find(currentText);                         if(count === 4){                             editable = false;                         }                     }                 }             }         }          GroupBox {             width: 200;             height: 120;             title: "定制风格";             ComboBox {                 anchors.top: parent.top;                 anchors.topMargin: 8;                 width: parent.width;                 //editable: true;                 model: ["Google" , "IBM" , "Digia"];                 style: ComboBoxStyle {                     dropDownButtonWidth: 20;                     background: Rectangle {                         implicitHeight: 24;                         border.width: control.editable ? 0 : 1;                         border.color: (control.hovered || control.pressed)? "blue" : "gray";                         color: (control.hovered || control.pressed)? "#e0e0e0" : "#c0c0c0";                         Canvas {                             width: 16;                             height: 18;                             anchors.right: parent.right;                             anchors.rightMargin: 2;                             anchors.top: parent.top;                             anchors.topMargin: 1;                             onPaint: {                                 var ctx = getContext("2d");                                 ctx.save();                                 ctx.strokeStyle = "black";                                 ctx.lineWidth = 2;                                 ctx.beginPath();                                 ctx.moveTo(1, 8);                                 ctx.lineTo(8, 16);                                 ctx.lineTo(15, 8);                                 ctx.stroke();                                 ctx.restore();                             }                         }                     }                     label: Text {                         anchors.left: parent.left;                         anchors.leftMargin: 2;                         width: parent.width - 22;                         height: parent.height;                         verticalAlignment: Text.AlignVCenter;                         horizontalAlignment: Text.AlignHCenter;                         text: control.currentText;                         color: (control.hovered || control.pressed) ? "blue" : "black";                     }                 }             }         }          GroupBox {             width: 200;             height: 236;             title: "月份输入";             ComboBox {                 anchors.top: parent.top;                 anchors.topMargin: 8;                 width: parent.width;                 editable: true;                 model: ListModel {                 }                 validator: IntValidator{ top: 12; bottom: 1; }                 onAccepted: {                     if(count < 12 && find(currentText) === -1){                         model.append({text: editText});                         currentIndex = find(currentText);                         if(count === 12){                             editable = false;                         }                     }                 }             }         }     } } 

下图是使用 qmlscene 记载 combobox_demo.qml 后的效果图。

下图是做了一些操作后的效果图。

我设计了 4 个 ComboBox 对象,把它们分别放在 4 个 GroupBox 里,这样可以利用 GroupBox 的标题和边框,分界清晰。Grid 定位器管理 4 个 GroupBox。

  • 名为 “只读电器” 的 ComboBox,使用一个字符串列表作为 model,最为简单。
  • “可编辑水果” 下拉列表框,使用 ListModel,允许编辑,在 onAccepted 信号处理器内插入用户输入的文本,带滤重功能。当下拉列表内的条目数量达到 4 时禁止编辑。
  • 名为 “月份输入” 的 ComboBox,使用了 IntValidator,只允许输入 1 至 12 这几个月份。其他的与 “可编辑水果” 类似。


2、ProgressBar

ProgressBar 进度条,用途大家都了解,这里就不赘述了。

  • minimumValue 表示最小值;maximumValue 表示最大值;value 是当前值,更新它进度条就会变化。
  • orientation 代表方向,默认取值 Qt.Horizontal,水平方向;要想进度条变垂直,设置其为 Qt. Vertical。
  • style,又见 style,无处不在的 style,它指向一个 ProgressBarStyle 来定制进度条的外观。 indeterminate 属性比较有意思,当你不知道实际进度时,设置它为 true,ProgressBar 就会变身为Busylndicator 了,请稍等,就不告诉你等多久……它的默认值为 false。

2.1 ProgressBarStyle

ProgressBarStyle 的 control 属性指向 ProgressBar 对象。currentProgress 是一个 0?1 的值,表示当前进度。background 用来绘制进度条的背景,progress 用来绘制进度。
QT开发交流+赀料君羊:714620761

2.2 进度条综合演示

import QtQuick 2.2 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.2  Rectangle {     width: 480;     height: 240;     color: "#a0b0a0";      Row {         anchors.fill: parent;         anchors.margins: 10;         spacing: 8;          ProgressBar {             minimumValue: 0;             maximumValue: 100;             value: 40;             width: 150;             height: 20;             Timer {                 interval: 1000;                 repeat: true;                 running: true;                 onTriggered: {                     if(parent.value < 99.1){                         parent.value += 1;                     }else{                         stop();                     }                 }             }         }          ProgressBar {             orientation: Qt.Vertical;             minimumValue: 0;             maximumValue: 1;             value: 0.2;             width: 20;             height: 200;             Timer {                 interval: 1000;                 repeat: true;                 running: true;                 onTriggered: {                     parent.value = Math.random();                 }             }         }          ProgressBar {             minimumValue: 0;             maximumValue: 1;             value: 0.2;             width: 80;             height: 16;             indeterminate: true;         }          Item {             width: 180;             height: parent.height;              ProgressBar {                 id: customProgress;                 anchors.centerIn: parent;                 minimumValue: 0;                 maximumValue: 1;                 value: 0.2;                 width: 160;                 height: 20;                 style: ProgressBarStyle {                     background: Rectangle {                         implicitWidth: 200;                         implicitHeight: 20;                         border.width: 1;                         border.color: control.hovered ? "green" : "gray";                         color: "lightgray";                     }                     progress: Rectangle {                         color: "#208020";                     }                 }             }              ProgressBar {                 id: percentProgress;                 anchors.top: customProgress.bottom;                 anchors.topMargin: 4;                 anchors.horizontalCenter: parent.horizontalCenter;                 minimumValue: 0;                 maximumValue: 1;                 value: 0.33;                 width: 160;                 height: 20;                 style: ProgressBarStyle {                     id: progressStyle;                     background: Rectangle {                         border.width: 1;                         border.color: control.hovered ? "green" : "gray";                         color: "lightgray";                     }                     progress: Rectangle {                         color: "#208020";                     }                     panel: Item {                         implicitWidth: 200;                         implicitHeight: 20;                          Loader {                             anchors.fill: parent;                             sourceComponent: background;                         }                         Loader {                             id: progressLoader;                             anchors.top: parent.top;                             anchors.left: parent.left;                             anchors.bottom: parent.bottom;                             anchors.margins: 3;                             z: 1;                             width: currentProgress * (parent.width - 6);                             sourceComponent: progressStyle.progress;                         }                         Text {                             color: "blue";                             text: currentProgress * 100 + "%";                             z: 2;                             anchors.centerIn: parent;                         }                     }                 }             }         }     } } 

设计了 5 个进度条,水平、垂直、忙等待这三个 ProgressBar 对象都很简单。id 为 customProgress 的 ProgressBar 对象只定制了 progress 和 label, 不必说了。

id 为 percentProgress 的 ProgressBar,进度条的填充部分与背景之间留了 3 个像素的空隙, 这是通过设置 progressLoader 的 anchors.margins 实现的。在定制 panel 时,我添加了一个 Text 对象,让它居中显示进度百分比。

下图是执行 “qmlscene progressbar_demo.qml” 命令的效果图。

版权声明:

作者: freeclashnode

链接: https://www.freeclashnode.com/news/article-1724.htm

来源: FreeClashNode

文章版权归作者所有,未经允许请勿转载。

免费节点实时更新

热门文章

最新文章

归档