![](/img/trans.png)
[英]How to notify QtQuick2 TableView that its contentHeight has changed to update its scroll bars?
[英]QtQuick - make TableView update its rowCount after its model has changed
我有一個TableView,要在創建后動態填充它-即,我從C ++應用程序中讀取了一個字符串列表,我希望將其設置為TableView的模型。 我為此使用了一個ListModel,我從TableView的Component.onCompleted中完全沒有問題。 但是,加載后,我還想從列表中選擇某些項目作為默認選項。 問題是,即使ListModel包含所有數據,TableView的rowCount屬性也不會更新,因此當我調用tableView.selection.select(indexOfTheDefaultItem)
,會收到警告“ TableViewSelection:索引超出范圍”。 我嘗試發出ListModel.dataChanged()
信號並在那里處理初始選擇,但這無濟於事,我也嘗試對所有我能找到的其他信號(onLayoutChanged,onModelChanged ...)進行處理,但沒有結果。 如果在第一次嘗試失敗后重新加載數據,它就可以工作,因為第一次嘗試中已經有一些行,因此選擇不會超出范圍。 因此,似乎唯一的問題是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();
}
}
當前行為是:我用此代碼打開窗口,listView充滿了從getTheListWithData方法讀取的字符串,但未選擇任何內容。 然后,當我重新加載數據時(為此有一個按鈕),由於代碼示例末尾的連接,再次調用了initList,這一次它選擇了所需的行。
正如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函數應該執行此操作,但不執行此操作。 我發現其他人也有相同問題的帖子,但到目前為止,他們的解決方案都沒有對我有用。 但這是我個人進行更多研究的問題,或者在最壞的情況下,這是另一個SO問題:)如果找到解決方案,我將更新此答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.