2016-07-08 13 views
0

作成した後に動的に塗りたいTableViewがあります。つまり、モデルとして設定したいC++アプリケーションから文字列のリストを読み込みますTableView。私はそれのためにListModelを使用して、私は問題なしでTableViewのComponent.onCompletedからそれを塗りつぶします。しかし、ロードされた後は、リストから特定の項目をデフォルトのオプションとして選択したいと考えています。問題は、ListModelにすべてのデータが含まれていても、TableViewのrowCountプロパティが更新されないため、tableView.selection.select(indexOfTheDefaultItem)を呼び出すと「TableViewSelection:index out of range」という警告が表示されることです。 私はListModel.dataChanged()信号を放射してそこの最初の選択を処理しようとしましたが、それは助けにはなりません、私は他のすべての信号(onLayoutChanged、onModelChanged ...)でもやってみました。最初の試行が失敗した後にデータをリロードすると、最初の試行の行がすでに存在するため、選択範囲が範囲外にならないため、正常に動作しません。だから、唯一の問題は、rowCountが私には遅すぎるまで更新されないということです(コンポーネントがレンダリングされた後かもしれません)。QtQuick - モデルが変更された後、TableViewをrowCountに更新します

最終的に問題は - 私が反応する可能性のあるrowCountが更新された後に何らかの信号が出ているのですか?? 私は、アプリケーションのC++側でリストを作成し、beginInsertRows()とendInsertRows()を使用するいくつかのソリューションを見てきましたが、これらは明らかにListViewの機能ではなく、コードをqmlに保持したいと考えています。 は、ここに私の解決策が今見えるものです:

ListModel 
{ 
    id:listModel 
} 
TableView 
{ 
    id: tableView 
    selectionMode:SelectionMode.SingleSelection 
    model: listModel 
    TableViewColumn 
    { 
     role: "myRole" 
     title: "myTitle" 
    } 
    onModelChanged // or Connections{target:listModel onDataChanged .... } or onAnythingThatWillWorkPlease: 
    { 
     if (tableView.rowCount > 0) // this prevents the "index out of range" warning, but does not really solve the problem 
     { 
      var defaultEntityIndex = 5; 
      tableView.currentRow = defaultEntityIndex; // when I don't call this, the code in the onSelectionChanged below has "null pointer" exception, i.e. I presume the currentRow stays at the initial -1 - hence this "hack" 
      tableView.selection.select(defaultEntityIndex); 
     } 
    } 
    Connections 
    { 
     target: tableView.selection 
     onSelectionChanged : 
     { 
      if (tableView.currentRow >= 0) 
       myC++Class.selectedThing = listModel.get(tableView.currentRow).role; 
     } 
    } 
} 
function initList() 
{ 
    var vals = myC++Class.getTheListWithData(); 
    for(var i =0; i<vals.length; i++) 
    { 
     listModel.append({role: vals[i]}); 
    } 
    tableView.model = listModel // I just tried to do this to trigger the modelChanged signal 
    listModel.dataChanged(0, vals.length - 1); 
} 
Component.onCompleted: 
{ 
    initList(); 
} 
Connections // this is to re-fresh the tableView when my data changes 
{ 
    target: myC++class 
    onDataChanged: // my custom signal 
    { 
     initList(); 
    } 
} 

現在の動作は次のとおりです。私はこのコードでウィンドウを開く、リストビューはgetTheListWithDataメソッドから読み、私の文字列で満たされているが、何も選択されていません。データをリロードすると(ボタンがあります)、コード例の最後にある接続のおかげでinitListが再び呼び出され、今回は必要な行が選択されます。

+1

'property int defaultEntityIndex'を追加し、' onRowCountChanged'でそれを使うのはどうですか? – Velkan

+0

これはまさに私が欲しいものです。前に試してみて欲しいと誓っています。それはうまくいきませんでした。しかし、コードに間違いがあったか、間違っているはずです(qmlのコード自動補完がない可能性が高いです)。 ...とにかく私はもう一度それを試して、それは動作します、ありがとう。あなたが答えとしてそれを作るなら、私はそれを受け入れるでしょう...それはおそらく削除することができる無駄な質問ですが、私はあなたに決めるでしょう:) – tomj

+0

それはあなた自身のいくつかのコードで答える。 StackOverflowでqt5の統計情報を向上させる。 – Velkan

答えて

1

Velkanがコメントで指摘したように、解決策は単にonRowCountChanged信号を使用することです。その後、期待どおりに動作します。以下は私の完全なコードです。

ListModel 
{ 
    id:listModel 
} 
TableView 
{ 
    id: tableView 
    selectionMode:SelectionMode.SingleSelection 
    model: listModel 
    TableViewColumn 
    { 
     role: "myRole" 
     title: "myTitle" 
    } 
    onRowCountChanged: 
    { 
     if (rowCount > 0) 
     { 
      var defaultEntityIndex = 0; 
      for (var i = 0; i < rowCount; i++) 
      { 
       if (model.get(i).role == qsTr("NameOfTheDefaultItem")) 
        defaultEntityIndex = i; 
      } 
      // select the default item and also set it as current so that it is highlighted 
      currentRow = defaultEntityIndex 
      selection.select(defaultEntityIndex) 
      // move the view to the item so that the user knows that something got selected without his input....though this function actually does not seem to be working 
      positionViewAtRow(defaultEntityIndex, ListView.Beginning) 
      focus = true  
     } 
    } 
    Connections 
    { 
     target: tableView.selection 
     onSelectionChanged : 
     { 
      if (tableView.currentRow >= 0) 
       myC++Class.selectedThing = listModel.get(tableView.currentRow).role; 
     } 
    } 
} 
function initList() 
{ 
    var vals = myC++Class.getTheListWithData(); 
    for(var i =0; i<vals.length; i++) 
    { 
     listModel.append({role: vals[i]}); 
    } 
    // the lines that were here in the original post are (as expected) not needed 
} 
Component.onCompleted: 
{ 
    initList(); 
} 
Connections // this is to re-fresh the tableView when my data changes 
{ 
    target: myC++class 
    onDataChanged: initList(); 
} 

もう一度、Velkanに感謝します。

TableViewをデフォルトの要素までスクロールして自動的に選択すると、ユーザーはこのデフォルトの選択が行われたことに気付くことになります。 positionViewAtRow関数はそれだけを行う必要がありますが、そうではありません。私は、同じ問題を抱えている他の人々の記事をいくつか見つけましたが、今のところ解決策はありませんでした。しかし、それは私の部分や最悪の場合、さらに多くの研究のための問題です。私は解決策を見つけるなら、私はこの答えを更新します。

関連する問題