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


    一、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 —般不用设置。


    1.2 ComboBox 综合演示

    combobox demo.qml 的内容如下:

    import QtQuick 2.2
    import QtQuick.Controls 1.2
    import QtQuick.Controls.Styles 1.2
    
    Rectangle {
         480;
        height: 360;
        color: "#a0b0a0";
    
        Grid {
            anchors.fill: parent;
            rows: 2;
            columns: 2;
            rowSpacing: 4;
            columnSpacing: 4;
            GroupBox {
                 200;
                height: 120;
                title: "只读电器";
                ComboBox {
                    anchors.top: parent.top;
                    anchors.topMargin: 8;
                     parent.width;
                    model: ["TV" , "CD Player" , "Set Top Box" , "Router"];
                }
            }
    
            GroupBox {
                 200;
                height: 120;
                title: "可编辑水果";
                ComboBox {
                    anchors.top: parent.top;
                    anchors.topMargin: 8;
                     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 {
                 200;
                height: 120;
                title: "定制风格";
                ComboBox {
                    anchors.top: parent.top;
                    anchors.topMargin: 8;
                     parent.width;
                    //editable: true;
                    model: ["Google" , "IBM" , "Digia"];
                    style: ComboBoxStyle {
                        dropDownButtonWidth: 20;
                        background: Rectangle {
                            implicitHeight: 24;
                            border. control.editable ? 0 : 1;
                            border.color: (control.hovered || control.pressed)? "blue" : "gray";
                            color: (control.hovered || control.pressed)? "#e0e0e0" : "#c0c0c0";
                            Canvas {
                                 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;
                             parent.width - 22;
                            height: parent.height;
                            verticalAlignment: Text.AlignVCenter;
                            horizontalAlignment: Text.AlignHCenter;
                            text: control.currentText;
                            color: (control.hovered || control.pressed) ? "blue" : "black";
                        }
                    }
                }
            }
    
            GroupBox {
                 200;
                height: 236;
                title: "月份输入";
                ComboBox {
                    anchors.top: parent.top;
                    anchors.topMargin: 8;
                     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 这几个月份。其他的与 “可编辑水果” 类似。


    二、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 用来绘制进度。


    2.2 进度条综合演示

    import QtQuick 2.2
    import QtQuick.Controls 1.2
    import QtQuick.Controls.Styles 1.2
    
    Rectangle {
         480;
        height: 240;
        color: "#a0b0a0";
    
        Row {
            anchors.fill: parent;
            anchors.margins: 10;
            spacing: 8;
    
            ProgressBar {
                minimumValue: 0;
                maximumValue: 100;
                value: 40;
                 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;
                 20;
                height: 200;
                Timer {
                    interval: 1000;
                    repeat: true;
                    running: true;
                    onTriggered: {
                        parent.value = Math.random();
                    }
                }
            }
    
            ProgressBar {
                minimumValue: 0;
                maximumValue: 1;
                value: 0.2;
                 80;
                height: 16;
                indeterminate: true;
            }
    
            Item {
                 180;
                height: parent.height;
    
                ProgressBar {
                    id: customProgress;
                    anchors.centerIn: parent;
                    minimumValue: 0;
                    maximumValue: 1;
                    value: 0.2;
                     160;
                    height: 20;
                    style: ProgressBarStyle {
                        background: Rectangle {
                            implicitWidth: 200;
                            implicitHeight: 20;
                            border. 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;
                     160;
                    height: 20;
                    style: ProgressBarStyle {
                        id: progressStyle;
                        background: Rectangle {
                            border. 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;
                                 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” 命令的效果图。


    参考:

    《Qt Quick核心编程》第9章


  • 相关阅读:
    Google 开源的 Python 命令行库:深入 fire(二)
    开启 Django 博客的 RSS 功能
    MongoDB 分片键的选择与案例
    Log4Net写入到数据库配置过程中的一些小问题备忘
    《WCF服务编程第三版》知识点摘录
    Android调用基于.net的WebService
    心跳包实现的另一种机制
    无法加载一个或多个请求的类型。有关更多信息,请检索 LoaderExceptions 属性。
    解决SaveChanges会Hold住之前的错误的问题
    memcached工作原理与优化建议
  • 原文地址:https://www.cnblogs.com/linuxAndMcu/p/11949814.html
Copyright © 2020-2023  润新知