具有动态列数的 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
的模式包含ListElement
s 并在其中定义了角色,但运行时它不会显示任何内容。
但是,如果取消注释上述代码并且定义了 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】:您可以使用TableView
的resources
属性,根据需要动态创建任意数量的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的主要内容,如果未能解决你的问题,请参考以下文章