2017-06-11 5 views
0

Ich habe eine MatrixQML Output Matrix

QVector<QVector<double>> A; 

, die ich ausgeben und bearbeiten möchten. In QWidgets setze ich diese Matrix in die QAbstractTableModel-Unterklasse und setze diese als Modell für QTableView. In qml scheint dies nicht mit TableView zu funktionieren.

Wie ich understood, für feste Größe Matrizen ich explizit Rollen für jede Spalte schreiben:

TableViewColumn { 
     role: "first" // "second", "third" etc. 
} 

Und dann für jede Rückkehr Rolle Spalte von QAbstractTableModel :: Daten entsprechen (...).

Aber was, wenn Matrixdimensionen in Laufzeit berechnet werden? Was ist der beste Weg, um mit solchen Matrizen in qml zu arbeiten?

+0

Ich denke, Sie sollten die Tabelle mit [einfügen Spalten] (http://doc.qt.io/qt-5/qabstractitemmodel.html#insertColumns), [removeColumns] (http://doc.qt.io/) qt-5/qabstractitemmodel.html # removeColumns), wenn sich Ihre Datenquelle geändert hat. – folibis

+0

@folibis: Ich denke nicht, dass das den Trick machen wird, denn afaik, QML interessiert sich nicht für Modellspalten. Ich denke, Sie sollten eine Eigenschaft, z. 'roleNames', die Sie dann als' Repeater' verwenden, um 'TableViewColumns' mit' role: modelData' zu erzeugen – derM

Antwort

0

Hinweis: Hacky sein könnte, sondern arbeitet

Ich habe nicht mit einem QAbstractTableModel und QML bisher gearbeitet, aber nach meinem Verständnis, QML kümmert sich nicht für Spalten, so sollte ein ListModel sein eine ausreichende subsitution für ein Beispiel:

import QtQuick 2.7 
import QtQml 2.2 
import QtQuick.Controls 1.4 

ApplicationWindow { 
    id: myWindow 
    visible: true 
    width: 600 
    height: 600 
    color: 'white' 

    ListModel { 
     id: lv 
     property var roleNames: ['role1', 'role2'] 
     ListElement { role1: 'a'; role2: 'b' } 
    } 

    ListModel { 
     id: tm 
     property var roleNames: [ 'myID', 'age', 'name'] 
     ListElement { myID: 1; name: 'Egon'; age: 15 } 
     ListElement { myID: 2; name: 'Herbert'; age: 21 } 
     ListElement { myID: 3; name: 'Jan';  age: 11 } 
     ListElement { myID: 4; name: 'Dieter'; age: 23 } 
     ListElement { myID: 5; name: 'Ulrich'; age: 6 } 
     ListElement { myID: 6; name: 'Hans'; age: 45 } 
     ListElement { myID: 7; name: 'Frieder'; age: 31 } 
     ListElement { myID: 8; name: 'Gerd'; age: 28 } 
    } 

    TableView { 
     id: tv 
     model: lv 
     anchors.fill: parent 
     Instantiator { 
      model: tv.model ? tv.model.roleNames : 0 
      delegate: TableViewColumn { 
       title: modelData 
       role: modelData 
       Component.onCompleted: tv.addColumn(this) 
       Component.onDestruction: tv.removeColumn(0) 
      } 
     } 
    } 

    MouseArea { 
     anchors.fill: parent 
     onClicked: tv.model = (tv.model === lv ? tm : lv) 
    } 
} 

durch ein zweites Modell Zugabe schaffe ich eine ausreichende Menge an und dementsprechend TableViewColumn s konfiguriert, dass ich dann fügen zu der TableView unter Verwendung einer Instantiator (wie TableViewColumn ist keine Item, wie es scheint).

Ein Problem, das hier auftritt, ist, dass ich keinen Weg finde, auf den Spaltenindex zuzugreifen, ich muss tv.removeColumn mit dem richtigen Index aufrufen. Aber in diesem Fall, wo ich immer das ganze Modell ersetze, ist das kein Problem, solange ich alle Spalten nacheinander lösche, indem ich immer die erste mit tv.removeColumn(0) entferne. Ich werde immer noch ein Fehler

Error: Invalid attempt to destroy() an indestructible object

da diese Methode destroy() auf einem Objekt aufzurufen versucht, die nicht mit JS erstellt wird, aber das ist kein Problem. Die Instantiator löscht es direkt danach.

Also: Obwohl es eine Fehlermeldung gibt, wird dies funktionieren, solange Sie das Modell der Instantiator jedes Mal zurücksetzen, wenn es eine Änderung gibt.