QtQuick - 使 TableView 在其模型更改后更新其 rowCount

标签 qt qml qtquick2 qtquickcontrols qt5.5

我有一个 TableView,我想在创建后动态填充它 - 即,我从我的 C++ 应用程序中读取了一个字符串列表,我想将其设置为 TableView 的模型。我为此使用了 ListModel,我从 TableView 的 Component.onCompleted 填充它没有任何问题。但是,加载后,我还想从列表中选择某些项目作为默认选项。问题是,即使 ListModel 包含所有数据,TableView 的 rowCount 属性也不会更新,因此当我调用 tableView.selection.select(indexOfTheDefaultItem) 时,我收到警告“TableViewSelection:索引超出范围”。 我尝试发出 ListModel.dataChanged() 信号并处理那里的初始选择,但这没有帮助,我还尝试对所有其他信号(onLayoutChanged、onModelChanged ...)执行此操作可以找到但没有结果。如果我在第一次失败的尝试后重新加载数据,它会起作用,因为第一次尝试已经有一些行,所以选择不会超出范围。所以看来唯一的问题是 rowCount 没有更新,直到对我来说为时已晚(也许是在组件渲染之后?)。

所以最终的问题是 - 在 rowCount 更新后是否会发出一些我可以使用react的信号? 我见过一些涉及在应用程序的 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 函数应该做到这一点,但没有。我发现其他人也有同样问题的一些帖子,但到目前为止他们的解决方案都不适合我。但这是我需要进行更多研究的问题,或者在最坏的情况下是另一个问题:)如果我找到解决方案,我会更新这个答案。

关于QtQuick - 使 TableView 在其模型更改后更新其 rowCount,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38263956/

相关文章:

Qt 忽略 SSL 错误

c++ - 具有多种颜色背景的 QPalette

c++ - 处理高速数据时避免 QSerialPort 超时

python-3.x - Python Tkinter GUI 与 PyQT 的内存节省

c++ - 获取光标下的控制权

python - PySide 和 QtWebKit : Module could not be found

ios - 出现错误 : module "QtPositioning" plugin "declarative_positioning" not found

c++ - OpenGL 和 QtQuick 纹理问题

javascript - QtQuick2-QML-创建无限动线动画

android - QML - 通过点击事件显示菜单栏或菜单项