在Qt Quick中从ListView制作自定义TableView的规范方法 [英] Canonical way to make custom TableView from ListView in Qt Quick

查看:138
本文介绍了在Qt Quick中从ListView制作自定义TableView的规范方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ListView制作表格的最佳方法是什么?

What is the best way to make table from ListView?

说,给定二维数组字符串,所有列的delegateLabel.仅使用QML时,如何以及何时计算每列的最大项目宽度?每个Label的内容不是恒定的(即implicitWidth在生命周期内是可变的).

Say, given a 2d array of strings and delegate for all the columns are Labels. How and when to calculate maximum item width for each column while using only QML? Content of each Label is not constant (i.e. implicitWidth is mutable during lifetime).

发明TableView的实际原因是事实,到TreeView的步骤仍将保留.

Practical reason to invent the TableView is the fact, that 1 step to TreeView will remain.

推荐答案

关于在QML中创建表的问题似乎经常发布,但是我还没有看到一个汇总所有不同选项的答案.有很多方法可以实现您的要求.我希望在此答案中提供多种选择.

Questions about creating tables in QML seem to get posted fairly frequently, but I am yet to see an answer compiling all the different options. There are lots of ways to achieve what you are asking. I hope to provide in this answer a number of alternatives.

(2019年1月14日更新)

(Updated 14 Jan 2019)

Qt 5.12包含一个新的名为TableView的Qt Quick项目,该项目从头开始进行了重新设计,以使其对于具有任意行或列数的数据模型都具有良好的性能.它解决了Quick Controls 1中以前TableView中存在的性能问题.

Qt 5.12 includes a new Qt Quick item called TableView, which has been redesigned from the ground up to have good performance for a data model with any number of rows or columns. It resolves the performance problems which were present in the previous TableView from`Quick Controls 1.

我无法提供此方法的使用示例,因为我还没有使用它(我的项目仍在使用Qt 5.9),但是Qt文档中有适用于5.12和更高版本的示例.

I cannot provide a usage example for this approach, because I haven't used it yet (I am still using Qt 5.9 for my projects), but there are examples in the Qt documentation for 5.12 and later.

  • Performance Comparison: http://blog.qt.io/blog/2018/12/20/tableview-performance/
  • Documentation: https://doc.qt.io/qt-5/qml-qtquick-tableview.html

如果您使用的是Qt 5.12,并且您知道表将同时需要水平滚动和垂直滚动(行和列的数量超出视图的容纳范围),那么这似乎是首选解决方案.

If you are using Qt 5.12, and you know that you will need both horizontal scrolling and vertical scrolling for your table (there are more rows AND columns than can fit in the view), then this would seem to be the first choice solution.

以下是Qt 5.11及更早版本的替代方法的摘要,或者如果您出于某种原因不想使用Qt 5.12 TableView(也许这些替代方法之一更适合您的数据模型?).

Below are a summary of alternative approaches for Qt 5.11 and earlier, or if for some reason you do not want to use the Qt 5.12 TableView (perhaps one of these alternative approaches better suits your data model?).

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    ListModel {
        id: listModel
        ListElement { name: 'item1'; code: "alpha"; language: "english" }
        ListElement { name: 'item2'; code: "beta"; language: "french" }
        ListElement { name: 'item3'; code: "long-code"; language: "long-language" }
    }

    GridLayout {
        flow: GridLayout.TopToBottom
        rows: listModel.count
        columnSpacing: 0
        rowSpacing: 0

        Repeater {
            model: listModel

            delegate: Label {
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.preferredHeight: implicitHeight
                Layout.preferredWidth: implicitWidth
                background: Rectangle { border.color: "red" }
                text: name
            }
        }
        Repeater {
            model: listModel

            delegate: Label {
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.preferredHeight: implicitHeight
                Layout.preferredWidth: implicitWidth
                background: Rectangle { border.color: "green" }
                text: code
            }
        }
        Repeater {
            model: listModel

            delegate: Label {
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.preferredHeight: implicitHeight
                Layout.preferredWidth: implicitWidth
                background: Rectangle { border.color: "blue" }
                text: language
            }
        }
    }
}

垂直ListView

使用Vertical ListView创建表有其优点和缺点. 优点:

Vertical ListView

Creating a table with the Vertical ListView has its advantages and disadvantages. Pros:

  • 可滚动
  • 动态创建可见区域之外的代表,这意味着加载速度更快
  • 易于创建固定宽度的列,在该列中文本被消除或包裹

缺点:

  • 对于垂直滚动ListView(通常这是人们想要的),动态列宽很难实现...即列宽设置为完全适合列中的所有值
  • For a vertical scrolling ListView (which is usually what people want), dynamic column width is difficult to achieve... i.e. column width is set to completely fit all values in the column

必须使用循环遍历该列内的所有模型数据来计算列宽,这可能很慢,并且您不希望经常执行此操作(例如,如果用户可以修改单元格内容并且您希望调整列的大小) ).

Column widths must be calculated using a loop over all the model data inside that column, which could be slow and is not something you would want to perform often (for example if user can modify cell contents and you want the column to resize).

在将模型分配给ListView时,仅计算一次列宽,并混合使用固定宽度和计算宽度的列即可实现合理的折衷.

A reasonable compromise can be achieved by only calculating the column widths once, when the model is assigned to the ListView, and having a mixture of fixed-width and calculated-width columns.

警告:以下是示例,该示例计算列宽以适合最长的文本.如果模型较大,则应考虑废弃Javascript循环,并采用固定宽度的列(或相对于视图大小的固定比例).

Warning: Below is an example of calculating column widths to fit longest text. If you have a large model, you should consider scrapping the Javascript loop and resort to fixed width columns (or fixed proportions relative to the view size).

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

ApplicationWindow {
    visible: true
    width: 640
    height: 480

    ListModel {
        id: listModel
        ListElement { name: 'item1'; code: "alpha"; language: "english" }
        ListElement { name: 'item2'; code: "beta"; language: "french" }
        ListElement { name: 'item3'; code: "long-code"; language: "long-language" }
    }

    ListView {
        property var columnWidths: ({"name": 100, "code": 50}) // fixed sizes or minimum sizes
        property var calculatedColumns: ["code", "language"]   // list auto sized columns in here

        orientation: Qt.Vertical
        anchors.fill: parent
        model: listModel

        TextMetrics {
            id: textMetrics
        }

        onModelChanged: {
            for (var i = 0; i < calculatedColumns.length; i++) {
                var role = calculatedColumns[i]
                if (!columnWidths[role]) columnWidths[role] = 0
                var modelWidth = columnWidths[role]
                for(var j = 0; j < model.count; j++){
                    textMetrics.text = model.get(j)[role]
                    modelWidth = Math.max(textMetrics.width, modelWidth)
                }
                columnWidths[role] = modelWidth
            }
        }

        delegate: RowLayout {

            property var columnWidths: ListView.view.columnWidths
            spacing: 0

            Label {
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.preferredHeight: implicitHeight
                Layout.preferredWidth: columnWidths.name
                background: Rectangle { border.color: "red" }
                text: name
            }

            Label {
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.preferredHeight: implicitHeight
                Layout.preferredWidth: columnWidths.code
                background: Rectangle { border.color: "green" }
                text: code
            }

            Label {
                Layout.fillHeight: true
                Layout.fillWidth: true
                Layout.preferredHeight: implicitHeight
                Layout.preferredWidth: columnWidths.language
                background: Rectangle { border.color: "blue" }
                text: language
            }
        }
    }
}

TableView(5.11和更早版本)

(来自Quick Controls 1)

TableView (5.11 and earlier)

(from Quick Controls 1)

QC1具有TableView组件. QC2没有(在Qt 5.9中).有一个正在开发中,但是没有保证的时间范围.

QC1 has a TableView component. QC2 does not (in Qt 5.9). There is one in development, but with no guaranteed timescale.

TableView一直不受欢迎,但是它确实在Quick Controls 1.0到1.4之间得到了改进,并且它仍然是可用的组件. QC1和QC2可以在同一应用程序中混合使用.

TableView has been unpopular due to performance issues, but it did receive improvements between Quick Controls 1.0 to 1.4, and it remains a useable component. QC1 and QC2 can be mixed in the same application.

优点

  • 易于实现电子表格样式的用户可调整大小的列
  • 基于ListView,因此可以很好地处理大量行.
  • 仅类似于Widget中QTableView的内置组件
  • easy to achieve spreadsheet-style user-resizable columns
  • based on a ListView, so handles large numbers of rows well.
  • only built-in component resembling the QTableView from Widgets

缺点

  • 默认样式是一种桌面灰色.与使用ListView从头开始相比,您可能要花更多的时间来尝试覆盖样式.
  • 自动调整列的大小以适合最长的内容不是很实际,也不是真的不可行.
  • default styling is a sort of desktop-grey. You might spend more time trying to override the styling than if you started from scratch using a ListView.
  • auto resizing columns to fit longest contents not really practical / doesn't really work.

示例:

import QtQuick 2.7
import QtQuick.Controls 1.4 as QC1
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3

ApplicationWindow {
    visible: true
    width: 400
    height: 200

    ListModel {
        id: listModel
        ListElement { name: 'item1'; code: "alpha"; language: "english" }
        ListElement { name: 'item2'; code: "beta"; language: "french" }
        ListElement { name: 'item3'; code: "long-code"; language: "long-language" }
    }

    QC1.TableView {
        id: tableView
        width: parent.width
        model: listModel

        QC1.TableViewColumn {
            id: nameColumn
            role: "name"
            title: "name"
            width: 100
        }
        QC1.TableViewColumn {
            id: codeColumn
            role: "code"
            title: "code"
            width: 100
        }
        QC1.TableViewColumn {
            id: languageColumn
            role: "language"
            title: "language"
            width: tableView.viewport.width - nameColumn.width - codeColumn.width
        }
    }
}

这篇关于在Qt Quick中从ListView制作自定义TableView的规范方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆