【问题标题】:Asynchronous Qt Model loading to QML GridView异步 Qt 模型加载到 QML GridView
【发布时间】:2016-01-20 16:19:20
【问题描述】:

我在将 QAbstractListModel 项目异步加载到 QML GridView 时遇到问题。当我执行将项目加载到模型的方法时,我必须等待每个项目都被加载。如何动态获取项目(即一项一项)?

我有相当大的模型对象,有 17 个字段(QStringQStringList'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


【解决方案1】:

看看this question。我相信你也有同样的问题。异步模型加载的问题在于您可以从单独的线程加载模型数据,即从非 GUI 线程调用 append(Item *item) 函数。但是您必须确保beginInsertRows(...)endInsertRows() 函数都从主GUI 线程运行。链接的问题说明了如何做到这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-14
    • 2018-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    相关资源
    最近更新 更多