在Qt Quick中从ListView制作自定义TableView的典型方法

时间:2017-07-18 13:47:53

标签: qt listview qml tableview qtquick2

<? public function manufacturer_models_list() { $manu_name = $this->manufacturer_name; $output = "<ul>"; sort($this->$manu_name); foreach ($this->$manu_name as $model) { switch($model) { //Output NOT repair.php on this list of strings case "ES400": case "MC9500": $output .= "<li>DIFFERENT OUTPUT</a></li>"; break; //default is the action that happens if none of the previous conditions are met default: $output .= "<li>" . "<a href=\"repair.php\">" . $model . "</a></li>"; break; } } $output .= "</ul>"; $output .= "<p class=\"clear\"></p>"; $output .= "<a href=\"repair.php\" " . "id=\"arrange-repair\">Arrange A Repair</a>"; return $output; } ?> 制作表格的最佳方法是什么?

假设,给定一个2d字符串数组,所有列的ListViewdelegate s。如何以及何时仅使用QML计算每列的最大项目宽度?每个Label的内容不是常数(即Label在生命周期内是可变的。)

发明implicitWidth的实际原因是,TableView的一步仍然存在。

1 个答案:

答案 0 :(得分:6)

关于在QML中创建表的问题似乎相当频繁地发布,但我还没有看到编译所有不同选项的答案。有很多方法可以实现您的要求。我希望在这个答案中提供一些替代方案。

TableView(5.12及更高版本)

(2019年1月14日更新)

Qt 5.12包含一个名为TableView的新Qt Quick项目,该项目已经从头开始重新设计,以便对具有任意数量的行或列的数据模型具有良好的性能。它解决了来自`快速控制1的先前TableView中出现的性能问题。

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

如果你正在使用Qt 5.12,并且你知道你需要水平滚动和垂直滚动你的表(有更多的行和列可以放在视图中),那么这似乎是首选溶液

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

GridLayout的

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
            }
        }
    }
}

垂直列表视图

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

  • 滚动
  • 动态创建可视区域之外的代理,这意味着加载速度更快
  • 易于为固定宽度的列创建,其中文本被省略或包裹

缺点:

  • 对于垂直滚动ListView(通常是人们想要的),动态列宽很难实现...即列宽设置为完全适合列中的所有值

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

通过仅计算列宽一次,将模型分配给ListView,并且具有固定宽度和计算宽度列的混合,可以实现合理的折衷。

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

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)

QC1有一个TableView组件。 QC2没有(在Qt 5.9中)。有一个正在开发中,但没有保证时间表。

由于性能问题,

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

赞成

  • 易于实现电子表格式用户可调整大小的列
  • 基于ListView,因此可以很好地处理大量行。
  • 仅与Widgets中的QTableView类似的内置组件

缺点

  • 默认样式是一种桌面灰色。与使用ListView从头开始创建样式相比,您可能会花费更多时间来覆盖样式。
  • 自动调整列大小以适应最长内容并不真正实用/无法正常工作。

示例:

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
        }
    }
}