You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

技术求助:从QML ListModel动态取数到C++并保存为QJsonObject

从QML ListModel提取数据并转为QJsonObject的实现方案

我来帮你搞定从QML ListModel动态取数据到C++并保存为QJsonObject的需求,结合你给出的代码片段,完整实现步骤如下:

1. 在QML中给ListModel设置可识别标识

首先要确保你的QML ListModel设置了objectName,这样C++代码才能准确定位到它:

ListModel {
    id: listModel
    objectName: "listModel" // 关键:C++通过这个名称查找对象

    // 示例数据,实际动态生成的内容也适用
    ListElement {
        name: "Apple"
        price: 5.99
        inStock: true
    }
    ListElement {
        name: "Banana"
        price: 3.49
        inStock: false
    }
}

2. 在C++中获取ListModel并遍历转JSON

在你的JsonCreator类中,新增方法提取ListModel数据并转为QJsonObject:

#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QFile>
#include <QFileInfo>
#include <QQmlApplicationEngine>
#include <QVariantMap>

class JsonCreator : public QObject
{
    Q_OBJECT
public:
    explicit JsonCreator(QObject *parent = nullptr);
    QString addUniqueSuffix(const QString path, const QString fileName) const;

public slots:
    void saveResults();

signals:
    void resultsDataChanged();

private:
    QJsonObject fetchListModelData(); // 新增:提取ListModel数据的方法
};

// 实现数据提取逻辑
QJsonObject JsonCreator::fetchListModelData()
{
    // 获取QML引擎根对象
    QQmlApplicationEngine* engine = qobject_cast<QQmlApplicationEngine*>(parent());
    if (!engine || engine->rootObjects().isEmpty()) {
        qWarning() << "Failed to access QML engine root objects";
        return {};
    }

    // 查找ListModel实例
    QObject* rootObj = engine->rootObjects().first();
    QObject* listModel = rootObj->findChild<QObject*>("listModel");
    if (!listModel) {
        qWarning() << "ListModel not found! Did you set objectName in QML?";
        return {};
    }

    // 获取元素总数并遍历
    int itemCount = listModel->property("count").toInt();
    QJsonArray itemArray;

    for (int i = 0; i < itemCount; ++i) {
        // 调用ListModel的get()方法获取单个元素的键值对
        QVariantMap itemMap = listModel->property("get").invoke(listModel, Q_ARG(int, i)).toMap();
        // 把键值对转为QJsonObject并加入数组
        QJsonObject itemJson = QJsonObject::fromVariantMap(itemMap);
        itemArray.append(itemJson);
    }

    // 把元素数组包装到最终的QJsonObject中
    QJsonObject finalJson;
    finalJson["listItems"] = itemArray;
    return finalJson;
}

3. 完善保存逻辑,结合唯一文件名生成

我帮你补全了addUniqueSuffix的缺失代码,并修改saveResults完成文件保存:

// 补全唯一文件名生成逻辑
QString JsonCreator::addUniqueSuffix(const QString path, const QString fileName) const {
    if (!QFile::exists(path + fileName)) {
        return fileName;
    }
    QFileInfo fileInfo(fileName);
    QString ret;
    QString suffix = fileInfo.completeSuffix();
    QString baseName = fileInfo.baseName();

    int counter = 1;
    do {
        // 生成带序号的文件名,比如results_1.json
        ret = QString("%1_%2.%3").arg(baseName).arg(counter).arg(suffix);
        counter++;
    } while (QFile::exists(path + ret));

    return ret;
}

// 完善保存方法
void JsonCreator::saveResults() {
    // 获取转换后的JSON对象
    QJsonObject resultsJson = fetchListModelData();
    if (resultsJson.isEmpty()) {
        qWarning() << "No data to save!";
        emit resultsDataChanged();
        return;
    }

    // 设置保存路径和基础文件名(可根据实际需求修改)
    QString saveDirectory = "./saved_data/";
    QString baseFileName = "results.json";

    // 创建保存目录(如果不存在)
    QDir dir(saveDirectory);
    if (!dir.exists()) {
        dir.mkpath(".");
    }

    // 获取唯一文件名并拼接完整路径
    QString uniqueFileName = addUniqueSuffix(saveDirectory, baseFileName);
    QString fullFilePath = saveDirectory + uniqueFileName;

    // 写入文件
    QFile saveFile(fullFilePath);
    if (saveFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QJsonDocument doc(resultsJson);
        // 写入格式化后的JSON,方便阅读
        saveFile.write(doc.toJson(QJsonDocument::Indented));
        saveFile.close();
        qInfo() << "Successfully saved data to:" << fullFilePath;
    } else {
        qWarning() << "Failed to open file for writing:" << saveFile.errorString();
    }

    emit resultsDataChanged();
}

关键注意事项

  • 数据类型兼容:ListModel中的元素类型需是QVariant可识别的基础类型(字符串、数字、布尔等),自定义类型需要提前注册为QMetaType才能正常转JSON。
  • QML引擎访问:如果JsonCreator不是QML引擎的子对象,需要调整引擎的获取方式(比如通过全局指针传递或构造函数传入)。
  • 权限与路径:确保保存目录有写入权限,否则会出现文件打开失败的问题。
  • 动态数据同步:如果ListModel数据是动态加载的,要确保调用saveResults时数据已稳定(比如等待加载完成的信号)。

内容的提问来源于stack exchange,提问作者Manmeet Sahi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:38:44