2014-12-01 15 views
7

Ho cercato di utilizzare un QML per visualizzare un QAbstractTableModel. La parte mancante dell'equazione sembra essere che non è possibile avere un numero variabile di colonne nello , nonostante l'override di QAbstractItemModel::roleNames che dovrebbe indicare a Qt il numero e il nome delle mie colonne. Ho provato prove utilizzando solo QML:QML TableView con numero dinamico di colonne

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

Quando eseguire questo non mostra nulla nonostante modalità s' il TableView contenente ListElement s con ruoli definiti in essi.

Tuttavia, se il codice sopra è uncommented e TableViewColumn è definita la colonna visualizza dati per quel ruolo come previsto ma la tabella non viene ancora mostrare altri ruoli. Ovviamente ciò funzionerà solo per un numero di colonne definito staticamente e non per il mio caso in cui il numero di colonne non è noto fino al runtime.

L'esempio fornito è fondamentalmente uguale al mio esempio di vita reale tranne che il mio modello è definito in C++.

Sembra che questo potrebbe essere già stato richiesto here ma non ha ottenuto alcuna risposta.

EDIT: avevo provato a chiamare una funzione 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); 
} 

Da C++:

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

Questo almeno mi ha permesso di aggiungere dinamicamente le colonne da C++, anche se non dal all'interno del modello/visualizza l'architettura. La soluzione di Yoann è di gran lunga migliore di questa però.

risposta

11

È possibile creare dinamicamente il numero TableViewColumn come necessario, utilizzando la proprietà resources del numero TableView.

Sarà necessario aggiungere un metodo nella classe del modello personalizzato che fornirà il ruoloNomi che si desidera visualizzare.

QML:

Component 
{ 
    id: columnComponent 
    TableViewColumn{width: 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(); 
} 

... 
... 
+2

Eccellente risposta! Ho dovuto scavare un po 'nella documentazione solo per trovare la proprietà 'resources' e anche da quella non avrei saputo che poteva essere usata in questo modo. – sjdowling

Problemi correlati