QML类型:TableView

一、描述

TableView 显示从内置 QML 类型(如 ListModel 和 XmlListModel)创建的模型中的数据,这些模型仅填充 TableView 中的第一列。要创建具有多列的模型,请使用 TableModel 或继承 QAbstractItemModel 的 C++ 模型。

TableView 继承了 Flickable。这意味着虽然模型可以有任意数量的行和列,但在视口内通常只能看到表格的一部分。 一旦轻弹,新的行和列就会进入视口,而旧的会退出并从视口中移除。 移出的行和列被重新用于构建移入视口的行和列。因此,TableView 支持任何大小的模型而不影响性能。

二、使用示例

2.1、C++模型

#include <qqml.h>
#include <QAbstractTableModel>

class testModel : public QAbstractTableModel
{
    Q_OBJECT
    QML_ELEMENT
    QML_ADDED_IN_MINOR_VERSION(1)

public:
    int rowCount(const QModelIndex & = QModelIndex()) const override
    {
        return 10;
    }

    int columnCount(const QModelIndex & = QModelIndex()) const override
    {
        return 5;
    }

    QVariant data(const QModelIndex &index, int role) const override
    {
        switch (role)
        {
            case Qt::DisplayRole:
                return QString("%1, %2").arg(index.column()).arg(index.row());
            default:
                break;
        }
        return QVariant();
    }
    QHash<int, QByteArray> roleNames() const override
    {
        return { {Qt::DisplayRole, "display"} };
    }
};
    qmlRegisterType<testModel>("com.mycompany.qmlcomponents", 1, 0, "TestModel");
import QtQuick 2.12
import QtQuick.Window 2.12
import Qt.labs.qmlmodels 1.0
import QtQuick.Controls 2.5
import com.mycompany.qmlcomponents 1.0

Window
{
    width: 800
    height: 400
    visible: true

    TableView
    {
        anchors.fill: parent
        columnSpacing: 1
        rowSpacing: 1
        clip: true

        model: TestModel
        {
        }

        delegate: Rectangle
        {
            implicitWidth: 100
            implicitHeight: 50
            Text
            {
                text: display
            }
        }
    }
}

2.2、QML模型

import QtQuick 2.12
import QtQuick.Window 2.12
import Qt.labs.qmlmodels 1.0

Window
{
    width: 400;height: 400
    visible: true

    TableView
    {
        anchors.fill: parent
        columnSpacing: 1
        rowSpacing: 1
        clip: true

        model: TableModel
        {
            TableModelColumn { display: "name" }
            TableModelColumn { display: "color" }

            rows:
            [
                {
                    "name": "cat",
                    "color": "black"
                },
                {
                    "name": "dog",
                    "color": "brown"
                },
                {
                    "name": "bird",
                    "color": "white"
                }
            ]
        }

        delegate: Rectangle
        {
            implicitWidth: 100
            implicitHeight: 50
            border.width: 1

            Text
            {
                text: display
                anchors.centerIn: parent
            }
        }
    }
}

三、重复使用项目

默认情况下,TableView 回收委托项,而不是在新行和新列被轻弹到视图时从委托实例化。这种方法提供了巨大的性能提升,具体取决于委托的复杂性。

当一个项目被弹出时,它会移动到重用池(未使用项目的内部缓存区)。这时会发出 pooled() 信号以通知该项目。同样,当项目从池中移回时,会发出 reused() 信号。

当项目被重用时,来自模型的任何项目属性都会更新。包括索引、行和列,还包括任何模型角色。

注意:应避免在委托中存储项目的任何状态。如果这样做,应在收到 reused() 信号时重置它。

如果项目有计时器或动画,应考虑在收到 pooled() 信号时暂停它们。这样就可以避免将 CPU 资源用于不可见的项目。同样,如果项目具有无法重用的资源,则可以将其释放。

如果不想重用项目或者如果委托不支持它,可以将重用项目 reuseItems 属性设置为 false。

注意:当一个项目在池中时,它可能仍然处于活动状态并响应连接的信号和绑定。

以下示例显示了一个为旋转矩形设置动画的委托。进入重用池时,动画暂时暂停:

Component 
{
    id: tableViewDelegate
    Rectangle 
    {
        implicitWidth: 100
        implicitHeight: 50

        TableView.onPooled: rotationAnimation.pause()
        TableView.onReused: rotationAnimation.resume()

        Rectangle 
        {
            id: rect
            anchors.centerIn: parent
            width: 40
            height: 5
            color: "green"

            RotationAnimation 
            {
                id: rotationAnimation
                target: rect
                duration: (Math.random() * 2000) + 200
                from: 0
                to: 359
                running: true
                loops: Animation.Infinite
            }
        }
    }
}

四、行高和列宽

当一个新列被轻弹到视图中时,TableView 将通过调用 columnWidthProvider() 函数来确定它的宽度。TableView 不存储行高或列宽,因为它旨在支持包含任意数量行和列的大型模型。

TableView 使用项中最大的隐式宽度(委托的 implicitWidth作为列宽,除非明确设置了 columnWidthProvider()。找到列宽后,同一列中的所有其他项目都将调整为该宽度,即使稍后轻弹的新项目具有更大的隐式宽度。在项目上设置显式宽度将被忽略并覆盖。

注意:列的计算宽度在从视口中弹出时会被丢弃,如果该列被弹回,则重新计算。计算始终基于该列弹入时可见的项目。这意味着该列的宽度每次都可能不同,具体取决于该列进入时所在的行。因此,应该对列中的所有项目具有相同的隐式宽度,或设置 columnWidthProvider() 。相同的逻辑适用于行高计算。

如果更改 rowHeightProvider() 或 columnWidthProvider() 为视口内的行和列返回的值,则必须调用 forceLayout()。这会通知 TableView 它需要再次使用提供程序函数来重新计算和更新布局。

如果要隐藏特定列,可以从该列的 columnWidthProvider() 返回 0。同样,可以从 rowHeightProvider() 返回 0 以隐藏行。如果返回负数,TableView 将回退以根据委托项计算大小。

        columnWidthProvider:function(column)
        {
            return 0
        }

注意:行或列的大小应为整数,以避免项目的亚像素对齐。

五、叠加层和底层

从委托实例化的所有新项目都作为 z 值为 1 的 contentItem 的父项。可以在 Tableview 中自行添加项目作为 Flickable 的子项目。通过控制它们的 z 值,可以使它们位于表格项目的顶部或底部。

在表格顶部添加一些文本,当轻弹时,这些文本会与表格一起移动:

import QtQuick 2.12
import QtQuick.Window 2.12
import Qt.labs.qmlmodels 1.0

Window
{
    width: 400;height: 400
    visible: true

    TableView
    {
        anchors.fill: parent
        columnSpacing: 1
        rowSpacing: 1
        clip: true
        topMargin: header.implicitHeight

        Text
        {
            z:2
            id: header
            text: "A table header"
        }

        model: TableModel
        {
            TableModelColumn { display: "name" }
            TableModelColumn { display: "color" }

            rows:
            [
                {
                    "name": "cat",
                    "color": "black"

                },
                {
                    "name": "dog",
                    "color": "brown"
                },
                {
                    "name": "bird",
                    "color": "white"
                }
            ]
        }

        delegate: Rectangle
        {
            implicitWidth: 100
            implicitHeight: 50
            border.width: 1

            Text
            {
                text: display
                anchors.centerIn: parent
            }
        }
    }
}

 

六、属性成员

1、bottomRow : int

      leftColumn : int

      rightColumn : int

      topRow : int

当前在视图中可见的最底部的行、最左边的列、最右边的列、最顶部的行。

2、columnSpacing : real

      rowSpacing : real

列间距、行间距。默认值为 0。

3、columnWidthProvider : var

此属性可以包含一个函数,该函数返回模型中每列的列宽。只要 TableView 需要知道特定列的宽度,就会调用它。该函数有一个参数 column 表示列数。

如果要隐藏特定列,可以为该列返回 0 宽度。如果返回负数,TableView 将根据委托项计算宽度。

      rowHeightProvider : var

类似,提供行高。

4、columns : int

      rows : int

只读属性,保存表中的列数、行数。

5、contentHeight : real

      contentWidth : real

此属性包含容纳数据模型中行数所需的表高度 / 宽度(不是 TableView 的高度 / 宽度)。如果知道表格的高度 / 宽度是多少,应为这些属性赋值,以避免对 TableView 进行不必要的计算和更新。

6、delegate : Component

委托提供了一个模板,定义了视图实例化的每个单元格项。 模型索引作为可访问的索引属性公开。 这同样适用于行和列。 根据数据模型的类型,模型的属性也可用。

委托应使用 Item::implicitHeight Item::implicitWidth 指定其大小。TableView 根据该信息布置项目。显式的宽度或高度设置将被忽略和覆盖。

注意:委托根据需要进行实例化,并且可以随时销毁。如果 reuseItems 属性设置为true,它们也会被重用。 因此,应该避免在委托中存储状态信息。

7、selectionModel : ItemSelectionModel

可以设置此属性来控制应将哪些委托项显示为选定项。

8、syncDirection : Qt::Orientations

该属性和 syncView 可以用来让两个tableView在轻弹时平滑同步。

如果设置了 syncView,则此属性控制两个表的轻弹方向的同步。默认为 Qt.Horizontal | Qt.Vertical,即如果向任一方向轻弹任一表,则另一个表也会向同一方向轻弹相同的量。

9、syncView : TableView

如果将一个 TableView 的这个属性设置为另一个 TableView,那么两个表格将根据 syncDirection 在轻弹、列宽/行高和间距方面进行同步。

  • 如果 syncDirection 包含 Qt.Horizontal,则当前 tableView 的列宽、列间距和水平滑动移动与syncView 的同步。
  • 如果 syncDirection 包含 Qt.Vertical,则当前 tableView 的行高、行间距和垂直滑动移动与syncView 的同步。

10、reuseItems 

此属性保存是否应重用从委托实例化的项目。

七、附加属性成员

1、TableView.view : TableView

此附加属性包含管理委托实例的视图。 它附加到委托的每个实例。

八、附加信号成员

1、pooled()

在将项目添加到重用池后发出此信号。可以使用它来暂停项目内正在进行的计时器或动画,或释放无法重复使用的资源。仅当 reuseItems 属性为 true 时才会发出此信号。

2、reused()

该信号在项目被重用后发出。此时,item已经从重用池中取出,放到 content view 里面,index、row、column等模型属性也都更新了。仅当 reuseItems 属性为 true 时才会发出此信号。

九、成员函数

1、Point cellAtPos(point position, bool includeSpacing)

      Point cellAtPos(real x, real y, bool includeSpacing)

返回视图中给定位置的单元格。如果没有单元格与 position 相交,则返回值为 point(-1, -1)。

如果 includeSpacing 设置为 true,则单元格的边界框将被视为包括每一侧相邻 rowSpacing columnSpacing 的一半。 默认值为false。

2、real columnWidth(int column)

返回给定列的宽度。 如果该列未加载(因此不可见),则返回值将为 -1。

应用程序负责通过使用 columnWidthProvider 来存储列宽。如果 TableView 没有设置 columnWidthProvider,则此函数最有用,否则可以调用 columnWidthProvider 设置的函数(即使对于当前不可见的列,它也可以工作。如果没有设置 columnWidthProvider,行高将等于它的implicitColumnWidth()。

      real rowHeight(int row)

类似,返回行高。

3、real implicitColumnWidth(int column)

返回给定列的隐式宽度。如果该列未加载(因此不可见),则返回值将为 -1。

列的隐式宽度是在该列内当前加载的委托项中找到的最大的隐式宽度。不会考虑 columnWidthProvider 返回的宽度。

      real implicitRowHeight(int row)

与上面类似。

4、bool isColumnLoaded(int column)

      bool isRowLoaded(int row)

是否加载了给定的列 / 行。

5、Item itemAtCell(point cell)

      Item itemAtCell(int column, int row)

如果加载,则返回单元格中的委托项,否则返回 null。

注意:通常只加载视图中可见的项目。一旦单元格从视图中弹出,里面的项目将被卸载或放置在回收池中。因此,永远不应存储返回值。

6、positionViewAtCell(point cell, Qt.Alignment alignment, point offset)

定位 Flickable::contentX Flickable::contentY 使参数1的单元格位于对齐指定的位置。

偏移量 offset 以将 contentX contentY 移动超出目标对齐方式的额外像素数。

想定位视图,使单元格 [10, 10] 以 5px 的边距位于左上角:

positionViewAtCell(Qt.point(10, 10), Qt.AlignLeft | Qt.AlignTop, Qt.point(-5, -5))
import QtQuick 2.12
import QtQuick.Window 2.12
import Qt.labs.qmlmodels 1.0

Window
{
    width: 400;height: 400
    visible: true

    TableView
    {
        id:view
        anchors.fill: parent
        columnSpacing: 1
        rowSpacing: 1
        clip: true

        model: TableModel
        {
            TableModelColumn { display: "name" }
            TableModelColumn { display: "color" }

            rows:
            [
                {
                    "name": "cat",
                    "color": "black"
                },
                {
                    "name": "dog",
                    "color": "brown"
                },
                {
                    "name": "bird",
                    "color": "white"
                }
            ]
        }

        delegate: Rectangle
        {
            implicitWidth: 100
            implicitHeight: 50
            border.width: 1

            Text
            {
                text: display
                anchors.centerIn: parent
            }
        }
    }
    MouseArea
    {
        anchors.fill: parent
        onPressed:
        {
            view.positionViewAtCell(Qt.point(1, 1), Qt.AlignLeft | Qt.AlignTop, Qt.point(-5, -25))
        }
    }
}

  • 10
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在QML中,可以使用TableView元素创建表格。使用model属性来指定表格的数据来源,其中的属性要使用TableModel类型。可以使用表头的visible属性和表头项来设置表格的表头。可以使用delegate属性和属性代理来设置表格中单元格的样式和内容。还可以使用resizeMode属性来设置表格的列宽自适应模式。最后,将TableView元素添加到适当的布局容器中来将表格放置在应用程序中。 ### 回答2: QML是一种基于Qt框架的声明式语言,用于快速开发并实现用户界面。其中,TableView就是一种常见的控件,用于展示多行多列的数据。 TableView的用法与其他控件类似,可以在QML文件中直接创建一个TableView: ``` TableView { // 设置表格的宽度和高度 width: 300 height: 200 // 设置表格的model(即数据),可以是Javascript中的数组或者ListModel等数据结构 model: ListModel { ListElement { name: "Tom"; age: 20 } ListElement { name: "Lucy"; age: 18 } ListElement { name: "Kate"; age: 22 } } // 设置表格的行和列的数量、宽度 TableViewColumn { role: "name"; title: "Name"; width: 100 } TableViewColumn { role: "age"; title: "Age"; width: 100 } } ``` 上述代码中,首先设置了TableView的宽度和高度,然后通过model属性设置了表格的数据。在这里,我们使用了ListModel,并将三个元素添加进去。接着,通过TableViewColumn设置了表格的列数以及每列进行展示的数据,例如第一列展示name,第二列展示age。 通过设置TableViewColumn还可以自定义每列的样式,例如: ``` TableViewColumn { role: "name" title: "Name" width: 100 delegate: Rectangle { color: "lightblue" border.color: "black" width: parent.width height: parent.height Text { text: styleData.value anchors.centerIn: parent } } } ``` 上述代码中,我们添加了一个Rectangle作为每列的样式,并且使用了Text组件来实现每个单元格的内容展示。 当然,除了上述基本用法以外,TableView还支持各种事件响应、滚动条控制等功能,可根据不同的需求进一步定制。总之,QMLTableView控件在展示多行多列的数据时非常实用,方便快捷易用。 ### 回答3: QML中的TableView有助于显示相对较大的表格数据。使用TableView时,您可以灵活地设置表格外观和排序规则。以下是如何使用TableView的一些示例。 首先,您需要导入QtQuick.Controls模块,以便可以使用TableView组件。 1. 基本用法 首先,在QML中创建一个TableView组件。然后,将表格列数据添加到model中。使用delegate设置每个单元格的外观。例如: ``` import QtQuick.Controls 1.4 TableView { TableViewColumn { role: "name" title: "Name" } TableViewColumn { role: "age" title: "Age" } model: ListModel { ListElement { name: "John" age: 30 } ListElement { name: "Mary" age: 40 } } delegate: Text { text: styleData.value } } ``` 在上面的例子中,我们定义一个表格,其中包含两列数据:name和age。model中包含两个元素,每个元素都包含名称和年龄。最后,我们将每个单元格的值设置为Text实例的文本属性。 2. SortDelegate和SortIndicator 可以使用SortDelegate和SortIndicator组件来为表格添加排序功能。SortDelegate将包含在表格的表头中。SortIndicator将指示按列排序的方向。 ``` import QtQuick.Controls 1.4 TableView { TableViewColumn { role: "name" title: "Name" sortIndicator: SortIndicator { column: 0 ascending: true } sortDelegate: Item { width: 10 Rectangle { anchors.fill: parent color: styleData.sortIndicatorColor } } } TableViewColumn { role: "age" title: "Age" sortIndicator: SortIndicator { column: 1 ascending: true } sortDelegate: Item { width: 10 Rectangle { anchors.fill: parent color: styleData.sortIndicatorColor } } } model: ListModel { ListElement { name: "John" age: 30 } ListElement { name: "Mary" age: 40 } } delegate: Text { text: styleData.value } } ``` 在上面的例子中,我们为每个列设置sortDelegate和sortIndicator,以便单击表头时实现升序和降序排序。 3. 带有扩展固定行的表格 也可以为表格添加一行或多行。 在这种情况下,表格将具有固定的标题行,而剩余的部分则可以滚动。 ``` import QtQuick.Controls 1.4 TableView { TableViewColumn { role: "name" title: "Name" } TableViewColumn { role: "age" title: "Age" } TableViewColumn { role: "email" title: "Email" } model: ListModel { ListElement { name: "John" age: 30 email: "john@example.com" } ListElement { name: "Mary" age: 40 email: "mary@example.com" } ListElement { name: "David" age: 35 email: "david@example.com" } ListElement { name: "Alice" age: 25 email: "alice@example.com" } } headerDelegate: Rectangle { height: 30 color: "gray" Text { text: model ? model.roleNames()[styleData.column] : "" font.bold: true anchors.centerIn: parent } } delegate: Text { text: styleData.value } } ``` 在此示例中,我们添加了一个headerDelegate,以显示在表格顶部的标题行。 headerDelegate设置了一个高度为30的矩形,其中包含TableColumn的标题。要添加固定行,我们将headerDelegate属性设置为Text,以便在表格顶部显示标题。 总结: 在QML中使用TableView可以轻松地显示表格数据。基本的TableView用法可以帮助您使用未排序或未分组的数据,但如果您需要更高级的功能,例如排序、固定行或多列滚动等,则可以使用SortDelegate和SortIndicator组件。最后,您还可以使用headerDelegate属性来为表格添加一个固定的标题行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值