• 【QML Model-View】TableView 使用


    TableView 就是 Qt Quick 为表格式呈现数据提供的组件。想必兄台用过 Excel,可以藉此想象下 TableView 的效果。

    TableView 与 ListView 类似,相比之下多了滚动条、挑选、可调整尺寸的表头等特性。 它的数据也通过 Model 来提供,你可以使用 ListModel、XmlListModel,也可以使用 C++ 中从 QAbstractltemModel、QAbstractTableModel 等继承而实现的 Model。

    使用 ListView 也可以将数据呈现为表格样式,不过稍微有些复杂,尤其是 delegate 的定义,当数据有很多列(比如播放列表、进销存管理、学生成绩表等)时,就会很复杂,再要有排序之类的操作,那就……此时就是 TableView 的用武之地了。

    一、—个简单的TableView实例

    下面是前面讲 ListView 时的示例,采用 TableView 来重写一下。QML 文件 phone_table_ simple.qml 的内容如下:

    import QtQuick 2.0
    import QtQuick.Window 2.3
    import QtQuick.Controls 1.2
    
    Window {
         360
        height: 360
        visible: true
    
        TableView{
            id: phoneTable
            anchors.fill: parent
            focus: true
    
            // TableViewColumn 描述表格的每一列
            TableViewColumn{role: "name"; title: "Name";  80; elideMode: Text.ElideRight;}
            TableViewColumn{role: "cost"; title: "Cost";  100;}
            TableViewColumn{role: "manufacture"; title: "Manufacture";  140;}
    
            model: ListModel{
                id: phoneModel
    
                ListElement{
                    name: "rongyao2";
                    cost: "4900";
                    manufacture: "huawei"
                }
    
                ListElement{
                    name: "s6";
                    cost: "4800";
                    manufacture :"sumsung"
                }
    
                ListElement{
                    name: "apple5"
                    cost: "3300"
                    manufacture: "apple"
                }
    
                ListElement{
                    name: "Mi5"
                    cost: "3200"
                    manufacture: "xiaomi"
                }
            } // model is end
    
        }
    }
    

    效果如下图所示:

    二、TableViewColumn 属性讲解

    定义了 TableViewColumn,描述表格的每一列,这是必需的,否则表格无法显示。示例中用到 role、title、width 三个属性,这是要使用 TableViewColumn 的最小属性集,role 对应 Model 中 ListElement 中的 role-name,正是这个属性完成了二维表格与一维 Model 之间的数据映射;title 是表头中一列的标题;width 定义列宽。

    • role、title、width

      这三个属性,是要使用 TableViewColumn 的最小属性集,role 对应 Model 中 ListElement 中的 role-name,正是这个属性完成了二维表格与一维 Model 之间的数据映射;title 是表头中一列的标题;width 定义列宽;

    • resizable

      定义一列的宽度是否可以调整,默认值为 true;

    • movable

      属性定义是否可以拖动一列的位置, 默认值为 true;

    • horizontalAlignment

      指定列标题文本的对齐方式,可以取 Text.AlignLeft (默认值)、Text.AlignRight、Text.AlignHCenter、Text.AlignJustify 四个值中的一个;

    • elideMode

      指定标题不能完整显示时的省略方式,可以取 Text.ElideRight (默认值)、Text.ElideLeft、 Text.ElideMiddle、Text.ElideNone 四个值中的一个;

    • visible

      布尔值,指定表格的一列是否显示,默认值为 true。

    TableViewColumn 的最后一个属性是 delegate,指定一个组件用来绘制这一列,示例中没有指定,釆取了默认值;在你提供的 delegate 中,可以访问 styleData 的部分属性来获知相关信息。styleData 是 TableView 相关的风格数据,有很多属性。下面所列的属性可以在 TableViewColumn 的 delegate 中访问:

    • styleData.selected,当 Item 选中时为 true。
    • styleData.value,当前 Item 的文本。
    • styleData.textColor,Item 的默认颜色。
    • styleData.row,行索引。
    • styleData.column,列索引。
    • styleData.elideMode,列省略模式。
    • styleData.textAlignment,列文本对齐方式。

    如你所见,我们仅仅是设置了 model,定义了表格的列属性,就得到了一个看起来还不错的表格,代码比我们使用 ListView 时少多了。

    如果你觉得默认的表格样式不好看,还可以定制它们。

    三、定制表格外观

    通过设置 itemDelegate、rowDelegate、headerDelegate 等属性,可以定制表格的外观。


    3.1 itemDelegate

    itemDelegate 属性指定如何绘制每一个单元格,它的类型是 Component。在 itemDelegate 中可以访问的 styleData 属性与 TableViewColumn 的 delegate —样。下面是一个 itemDelegate 定义实例:

    // 设置每个单元格的字体样式
    itemDelegate: Text {
        text: styleData.value
        color: styleData.selected ? "red" : styleData.textColor
        elide: styleData.elideMode
    }
    

    上面的 ItemDelegate 只有一个 Text 对象,它的 text 属性被设置为 styleData.value 。如果本 Item 被选中,文本颜色用红色,否则就用 styleData.textColor 文本如果显示不全,就采用 styleData.elideMode 指定的省略模式(在默认模式下省略号在右侧)。

    itemDelegate 并不局限于一个简单的可见 Item,你可以组合多个可见元素来实现复杂的 itemDelegate,比如在单元格内放置一个复选框、一个图片等。


    3.2 rowDelegate

    rowDelegate 属性指定如何绘制行背景,它的高度将决定 TableView 的行高。 rowDelegate 可以访问下列 styleData 属性(你可以理解成每一行都有这些属性可用):

    • styleData.altemate,本行使用交替的背景颜色时为true。
    • styleData.selected,本行被选中时为 true。
    • styleData.row,本行的索引。

    下面是一个 rowDelegate 实例:

    // 设置行的背景色
    rowDelegate: Rectangle {
        color: styleData.selected ? root.highlight : root.alterBackground
    }
    

    在上面的 rowDelegate 中,我用一个 Rectangle 作为行背景元素,根据是否使用交替背景、是否选中为行指定了不同的背景色。


    3.3 headerDelegate

    headerDelegate 属性定义如何绘制表头,它可以访问下列 styleData 附加属性:

    • styleData.value,本 Item 的值。

    • styleData.column,本列索引。

    • styleData.pressed,本列被按下(如鼠标左键按下或手指按下)时为 true。

    • styleData.containsMouse,鼠标是否停在本列内。

    • styleData.textAlignment,本列文本的水平对齐方式。

    下面是一个 headerDelegate 实例:

    // 渐变色
    property var normalG: Gradient {
        GradientStop { position: 0.0; color: "#c7d3ac" }
        GradientStop { position: 1.0; color: "#F0F0F0" }
    }
    property var hoverG: Gradient {
        GradientStop { position: 0.0; color: "white"; }
        GradientStop { position: 1.0; color: "#d7e3bc"; }
    }
    property var pressG: Gradient {
        GradientStop { position: 0.0; color: "#d7e3bc"; }
        GradientStop { position: 1.0; color: "white"; }
    }
    // ...
    
    // 设置表头的样式
    headerDelegate: Rectangle {
        implicitWidth: 10
        implicitHeight: 24
        gradient: styleData.pressed ? root.pressG : (styleData.containsMouse ? root.hoverG: root.normalG)
        border. 1
        border.color: "gray"
        
        Text {
            anchors.verticalCenter: parent.verticalCenter
            anchors.left: parent.left
            anchors.leftMargin: 4
            anchors.right: parent.right
            anchors.rightMargin: 4
            text: styleData.value
            color: styleData.pressed ? "red" : "blue"
            font.bold: true
        }
    }
    

    我通过 headerDelegate 改变了默认的表头外观,使用渐变色来填充表头背景,为鼠标按下、经过定义了不同的背景颜色和文本颜色。


    3.4 定制表格外观后的示例

    现在让我们修改一下 phone_table_simple.qml 示例,为 TableView 添加 itemDelegate、 rowDelegate、headerDelegate,改变 TableView 的外观。新的 QML 文件是 phone_table_delegate.qml,内容如下:

    import QtQuick 2.2
    import QtQuick.Controls 1.2
    
    Rectangle {
         360
        height: 300
        id: root
    
        property var background: "#d7e3bc"
        property var alterBackground: "white"
        property var highlight: "#e4f7d6"
        property var headerBkgnd: "#F0F0F0"
        property var normalG: Gradient {
                GradientStop { position: 0.0; color: "#c7d3ac" }
                GradientStop { position: 1.0; color: "#F0F0F0" }
        }
        property var hoverG: Gradient {
                GradientStop { position: 0.0; color: "white"; }
                GradientStop { position: 1.0; color: "#d7e3bc"; }
        }
        property var pressG: Gradient {
                GradientStop { position: 0.0; color: "#d7e3bc"; }
                GradientStop { position: 1.0; color: "white"; }
        }
    
        TableView {
            id: phoneTable
            focus: true
            anchors.fill: parent
            TableViewColumn{ role: "name"  ; title: "Name" ;  100; elideMode: Text.ElideRight;}
            TableViewColumn{ role: "cost" ; title: "Cost" ;  100; }
            TableViewColumn{ role: "manufacture" ; title: "manufacture" ;  140; }
    
            // 设置每个单元格的字体样式
            itemDelegate: Text {
                text: styleData.value
                color: styleData.selected ? "red" : styleData.textColor
                elide: styleData.elideMode
            }
    
            // 设置行的背景色
            rowDelegate: Rectangle {
                color: styleData.selected ? root.highlight : root.alterBackground
            }
    
            // 设置表头的样式
            headerDelegate: Rectangle {
                implicitWidth: 10
                implicitHeight: 24
                gradient: styleData.pressed ? root.pressG : (styleData.containsMouse ? root.hoverG: root.normalG)
                border. 1
                border.color: "gray"
    
                Text {
                    anchors.verticalCenter: parent.verticalCenter
                    anchors.left: parent.left
                    anchors.leftMargin: 4
                    anchors.right: parent.right
                    anchors.rightMargin: 4
                    text: styleData.value
                    color: styleData.pressed ? "red" : "blue"
                    font.bold: true
                }
            }
    
            model: ListModel {
                id: phoneModel
    
                ListElement{
                    name: "rongyao2";
                    cost: "4900";
                    manufacture: "huawei"
                }
                ListElement{
                    name: "s6";
                    cost: "4800";
                    manufacture :"sumsung"
                }
                ListElement{
                    name: "apple5"
                    cost: "3300"
                    manufacture: "apple"
                }
                ListElement{
                    name: "Mi5"
                    cost: "3200"
                    manufacture: "xiaomi"
                }
            }
    
        }
    }
    

    效果图如下:

    四、动态增删改查 TabelView

    有时你可能会想给 TableView 添加一列(一个字段),这时可以使用addColumn()方法, 其参数是 TableViewColumn,指向一个 TableViewColumn 实例,你可以动态创建这个实例。

    对于前两节的示例,第三列可以这样添加进去:

    Component.onCompleted: {
    	var col = Qt.createQmlObject("import QtQuick 2.2
    import QtQuick.Controls 1.2
    TableViewColumn{ role: "mamifacturer"; title: "Manufacturer";  140; }", phoneModel);
    	phoneTable.addColumn( col );
    }
    

    要想在指定位置添加一列,可以使用insertColumn(index, column)方法,index 参数指定列的索引,column 参数与 addColumn() 的参数一样。

    如果你想删除某列,可以使用removeColumn(index)方法,指定列索引即可。

    TableView 还提供了moveColumn(from, to),用于将一列从位置 from 移动到 to。

    而如果你想给 TableView 动态添加数据,则可以通过调用 ListModel 的 append() 或 insert() 方法实现。删除数据通过 ListModel 的 clear() 或 remove() 方法实现。这些在前面介绍 ListView 的时候都已经介绍过了。

    对于自定义的 Model,比如在 C++ 中实现的,则需要提供增、删、改数据的接口。 TableView 就介绍到这里了,进一步的应用请结合示例和 Qt 帮助学习。


    参考:

    《Qt Quick核心编程》第13章


  • 相关阅读:
    Android常用命令
    kafka原理和集群配置
    zookeeper原理和集群配置
    python中is和==的区别以及全字段取出key和value
    Android Monkey压力测试介绍
    有一串随机整数列,a1,a2,...an,求数字[0-9]分别出现的次数,比如:[12, 210, 33]输出{'0': 1, '1': 2, '2': 2, '3': 2},时间和空间复杂度
    接口自动化get请求方式的处理
    读excel和openpyxl模块
    linux上安装Docker
    [数据结构]堆的建立和排序
  • 原文地址:https://www.cnblogs.com/linuxAndMcu/p/13652479.html
Copyright © 2020-2023  润新知