【发布时间】:2016-01-20 16:19:20
【问题描述】:
我在将 QAbstractListModel 项目异步加载到 QML GridView 时遇到问题。当我执行将项目加载到模型的方法时,我必须等待每个项目都被加载。如何动态获取项目(即一项一项)?
我有相当大的模型对象,有 17 个字段(QString 和 QStringList's)。对象包含在自定义模型中:
class MyListModel : public QAbstractListModel
{
Q_OBJECT
public:
enum ListItemRole {
IdRole = Qt::UserRole,
VisualIndexRole,
NameRole,
...
};
MyListModel(QObject *parent = 0)
: QAbstractListModel(parent)
{
}
int rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_data.size();
}
QVariant data(const QModelIndex &index, int role) const
{
if( !index.isValid() || index.row() >= m_data.size() || index.row() < 0)
return QVariant();
switch(role) {
case NameRole:
return QVariant(m_data.at(index.row())->name());
...
(rest of the roles)
...
}
}
QHash<int, QByteArray> roleNames() const
{
QHash<int, QByteArray> roles;
roles[IdRole] = "folderName";
...
return roles;
}
private:
QList<Item*> m_data;
}
我正在通过 append 方法将项目插入模型:
void append(Item *item)
{
beginInsertRows(QModelIndex(), m_data.size(), m_data.size());
m_data.append(item);
endInsertRows();
}
Items 在其他函数中循环创建。此函数从 3 个 JSON 文件加载数据。加载 50 个项目大约需要 2 秒。
在这个列表模型之上,有两个QSortFilterProxyModel负责排序和过滤视图。过滤模型注册为QML类型,在GridView中使用。
我尝试了什么:
- 对创建项目的函数使用
QtConcurrent::run()方法 - FAIL(每个项目后不刷新视图) - 为每个列表项创建
QThread,并使用Worker类加载它 - FAIL(应用程序的崩溃和奇怪行为,即空项目、委托之间的空白空间以及 - 如第一点 - 不是异步的) - 将模型移动到
QThread并在Worker类中使用项目创建循环 - 部分成功(当我使用QCoreApplication::processEvents(QEventLoop::AllEvents,100);作为睡眠功能时,我可以逐个获取项目,但存在严重的性能问题和 - 作为我读过 - 这不是好方法)
我的问题有什么可能的解决方法吗?
【问题讨论】:
-
请参阅this answer 了解一些想法。
-
你为什么不
emit dataChanged()发信号?实际上,在 QML UI 的情况下,每次模型内容更改时都应该发出它来同步您的 UI。这是避免 UI 元素长时间冻结的方法。检查此段doc.qt.io/qt-5/qabstractitemmodel.html#dataChanged。对不起,如果它没有回答你的问题。我希望它有所帮助。
标签: c++ qt gridview asynchronous qml