具有动态列数的 QML TableView

Posted

技术标签:

【中文标题】具有动态列数的 QML TableView【英文标题】:QML TableView with dynamic number of columns 【发布时间】:2014-12-01 14:42:49 【问题描述】:

我一直在尝试使用 QML TableView 来显示 QAbstractTableModel。等式的缺失部分似乎是在TableView 中不可能有可变数量的列,尽管覆盖了QAbstractItemModel::roleNames,它应该告诉Qt 我的列的数量和名称。我尝试仅使用 QML 对此进行测试:

import QtQuick 2.0
import QtQuick.Controls 1.1

Rectangle 
    anchors.fill: parent
    property real showImage: 1.0
    width: 500
    TableView 
        id: myTable
        model: myModel
        //        TableViewColumn 
        //            role: "title"; title: "Name"; width: 200
        //        
    

    ListModel 
        id: myModel
        ListElement 
            title: "item one"
        
        ListElement 
            title: "item two"
        
    

尽管TableView 的模式包含ListElements 并在其中定义了角色,但运行时它不会显示任何内容。

但是,如果取消注释上述代码并且定义了 TableViewColumn,则该列将按预期显示该角色的数据,但该表仍不会显示任何其他角色。显然,这仅适用于静态定义的列数,而不适用于直到运行时才知道列数的情况。

给出的示例与我的实际示例基本相同,只是我的模型是用 C++ 定义的。

似乎这可能已经被问过here,但它没有得到任何回应。

编辑:我曾尝试调用 javascript 函数:

function addColumnToTable(roleName) 
    var columnString = 'import QtQuick 2.3; import QtQuick.Controls 1.2; TableViewColumn role: "'
            + roleName + '"; title: "' + roleName + '"; width: 40';
    var column = Qt.createQmlObject(
                columnString
                , myTable
                , "dynamicSnippet1")
    myTable.addColumn(column);

来自 C++:

QVariant roleName = "name";
QObject *root = view->rootObject();
QMetaObject::invokeMethod(root, "addColumnToTable", Q_ARG(QVariant, roleName));

这至少允许我从 C++ 动态添加列,尽管不是从模型/视图架构中。 Yoann 的解决方案远比这要好。

【问题讨论】:

【参考方案1】:

您可以使用TableViewresources 属性,根据需要动态创建任意数量的TableViewColumn

您必须在自定义模型类中添加一个方法,该方法将为您提供要显示的角色名称。

QML:

Component

    id: columnComponent
    TableViewColumnwidth: 100 


TableView 
    id: view
    anchors.fill: parent
    resources:
    
        var roleList = myModel.customRoleNames
        var temp = []
        for(var i=0; i<roleList.length; i++)
        
            var role  = roleList[i]
            temp.push(columnComponent.createObject(view,  "role": role, "title": role))
        
        return temp
    

    model: myModel

MyModel.h:

class MyModel: public QAbstractListModel

    Q_OBJECT
    Q_PROPERTY(QStringList userRoleNames READ userRoleNames CONSTANT)

public:
    explicit MyModel(QObject *parent = 0);

    enum MyModelRoles 
        UserRole1 = Qt::UserRole + 1,
        UserRole2,
        ...
    ;

    QStringList userRoleNames();
    int rowCount(const QModelIndex & parent = QModelIndex()) const;
    QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
    ...

private:
    QHash<int, QByteArray> roleNames() const;
    ...

;

MyModel.cpp:

...
...

QHash<int, QByteArray> MyModel::roleNames() const 
    QHash<int, QByteArray> roles = QAbstractListModel::roleNames ();
    roles[UserRole1] = "whatever";
    roles[UserRole2] = "youwant";
    return roles;


QStringList MyModel::userRoleNames() // Return ordered List of user-defined roles

    QMap<int, QString> res;
    QHashIterator<int, QByteArray> i(roleNames());
    while (i.hasNext()) 
        i.next();
        if(i.key() > Qt::UserRole)
            res[i.key()] = i.value();
    
    return res.values();


...
...

【讨论】:

优秀的答案!为了找到resources 属性,我不得不深入研究文档,即使这样我也不知道它可以以这种方式使用。【参考方案2】:

资源解决方案对我不起作用(Qt 5.6)。 TableView 没有更新。

这对我有用:

Component
    id: columnComponent
    TableViewColumnwidth: 30 


TableView 
    id: tableView
    model: listModel
    property var titles: somethingDynamic
    property var curTitles: 
        var t=[]
        for(var i=0;i<columnCount;i++)
            t.push(getColumn(i).title)
        
        return t
    
    onTitlesChanged:
        for(var i=0;i<titles.length;i++)
            if(curTitles.indexOf(titles[i])==-1)
                var column = addColumn(columnComponent) 
                column.title=titles[i]
                column.role=titles[i]                   
            
        
        for(var i=curTitles.length-1;i>=0;i--)
            if(titles.indexOf(curTitles[i])==-1)
                removeColumn(i)
            
        
    

它还可以正确更新拖放重新排序的列。

【讨论】:

以上是关于具有动态列数的 QML TableView的主要内容,如果未能解决你的问题,请参考以下文章

Android:具有动态列数的列表视图

如何在工作表中动态创建具有列数的数组,以删除多列中的重复项

构建具有不同列数的html表

具有不同列数的数据表

如何在 NativeScript 中创建具有动态行数和列数的表?

如何将具有未知列数的 ResultSet 映射到 List 并将其显示在 HTML 表中?