我打算创建自己的项目模型,派生自QAbstractItemModel。该模型不包含数据,但包含一些数据存储库。在插入,删除,重命名项目等之后,该存储库会发出信号。
每当存储库中的某些内容发生变化时,我的项目模型都需要转发这些信号。
然而,存储库具有独立信号,如void itemRemoved(int index);
,而QAbstractItemModel具有开始/结束对受保护功能(和信号),如beginInsertRows()
和endInsertRows()
。
我应该如何处理?例如。我可以将以下插槽连接到存储库的itemRemoved()
信号:
void RepositoryItemRemoved(int i)
{
beginInsertRows(QModelIndex(), i, i);
endInsertRows();
}
基于上面的示例:在存储库中插入行之后,是否有效地调用beginInsertRows()
/ endInsertRows()
?
答案 0 :(得分:1)
我有一个类似的场景,数据在不同的对象中,模型只是一个包装器,只有在视图中显示该数据集时才会创建。我在数据对象中使用了一个指向模型对象的指针,检查它是否在插入操作中为空,如果没有通过它调用beginInsertRows()
和endInsertRows()
。当然,由于这些是受保护的,因此必须将数据类声明为模型类的朋友。
文档强调在插入任何数据之前调用beginInsertRows()
非常重要:
在子类中重新实现insertRows()时,必须调用它 在将数据插入模型的底层数据存储之前的函数...
...否则,视图可能会以无效状态结束。
您应该使用视图进行测试,或者检查源中的实际实现。
答案 1 :(得分:0)
我也有类似的情况,只是在我的情况下,Qt模型将底层模型包含在字面上:底层模型包含的数据远远超过视图必须知道的数据。所以我让Qt模型包含自己的每个底层模型的数据项的小块列表供视图/委托处理。因此,处理底层模型更新的插槽如下所示:
List<string[]> fileContents = new List<string[]>();
var lines = File.ReadAllLines(ofd.FileName).ToList();
foreach (var item in lines)
{
string RegNo = string.Format("{0}", item.ToString().Substring(0, 19));
string accHolder = string.Format("{0}", item.ToString().Substring(21, 30));
string amount = string.Format("{0}", item.ToString().Substring(52, 11));
string accNo = string.Format("{0}", item.ToString().Substring(64, 13));
string branch = string.Format("{0}", item.ToString().Substring(78, 6));
string date = string.Format("{0}-{1}-{2}", "20" + item.ToString().Substring(85, 2), item.ToString().Substring(87, 2), item.ToString().Substring(89, 2));
string code = string.Format("{0}", item.ToString().Substring(92, 2));
string orphenColumn = string.Format("{0}", item.ToString().Substring(95, 1));
lstRegNo.Add(RegNo.Trim());
lstAccHolder.Add(ExtensionMethods.RemoveSpecialCharacters(accHolder.Trim()));
lstAmount.Add(amount.Trim());
lstAccNo.Add(accNo.Trim());
lstBranch.Add(branch.Trim());
lstDate.Add(date);
lstCode.Add(code.Trim());
lstOrphenColumn.Add(orphenColumn);
}
这样的设计解决了视图无效状态的问题,尽管对于让Qt模型包含其自己的项目列表的用例可能是不切实际的,这意味着要复制正在使用的足够数量的数据。