Qt/halcon 总结halcon字典数据用法和QDataSteam序列化与反序列化结构体实例

这就是一篇记录学习Halcon dict 字典在Qt/C++环境中处理数据的笔记总结,以及实际项目中开发遇到的问题延伸汇总。

目录导读

一、Halcon字典数据的增删查改

当前示例适用于halcon 24.0左右版本

1.创建halcon字段并赋值

cpp 复制代码
HTuple  hv_DictHandle;
//hv_DictHandle=dict{}
//创建一个空字典`
CreateDict(&hv_DictHandle);
//1. 添加键值对等同于修改
SetDictTuple(hv_DictHandle, "score", 95);
//2.添加图像对象
HObject  ho_Image;
ReadImage(&ho_Image, "particle");
SetDictObject(ho_Image, hv_DictHandle, "particle_image");

2.读取字段数据

cpp 复制代码
HTuple  hv_Exists, hv_ScoreValue;
//!  判断是否有当前字段,如果明知有可以直接提取`
GetDictParam(hv_DictHandle, "key_exists", "score", &hv_Exists);
if (0 != hv_Exists)
{ 
    GetDictTuple(hv_DictHandle, "score", &hv_ScoreValue); 
    //! 或者 
    hv_ScoreValue=hv_DictHandle.TupleGetDictTuple("epoch") ; 
} 

3.删除键值对

cpp 复制代码
RemoveDictKey(hv_DictHandle, "score");

4.复制HTuple,不限于字典类型

直接使用=号赋值,相当于指针引用。

cpp 复制代码
HTuple hv_DLDataset1;
CopyDict(hv_DictHandle, HTuple(), HTuple(), &hv_DLDataset1);

5.读取和写入HTuple 结构数据

cpp 复制代码
WriteDict(hv_DictHandle, "Text_DictHandle.hdict", HTuple(), HTuple());
ReadDict("Text_DictHandle.hdict", HTuple(), HTuple(), &hv_DictHandle);

6.HTuple字典插入元组数据

cpp 复制代码
//替换某处值
SetDictTupleAt(hv_DictHandle, "元组名称", 0, HTuple());
//被替换后重新添加
SetDictTuple(hv_DictHandle, "元组名称", (hv_DictHandle.TupleGetDictTuple("元组名称")).TupleConcat(hv_ImageItem));

7.HTuple字典元组删除某项

cpp 复制代码
 HTuple hv_indexss = -1;
  //查找第一个
  TupleFindFirst(hv_DictHandle.TupleGetDictTuple("元组名称"), hv_ImageItem, &hv_indexss);
  //移除索引项
  //tuple_remove (DictHandle.Mapdepot, indexss, Reduced)
  TupleRemove(hv_DictHandle.TupleGetDictTuple("元组名称"), hv_indexss, &hv___Tmp_Ctrl_0);
  //更新
  SetDictTuple(hv_DictHandle, "元组名称", hv___Tmp_Ctrl_0);

8.HTuple字典遍历所有字段

cpp 复制代码
//! 获取所有键值
GetDictParam(hv_Divide, "keys", HTuple(), &hv_Keys);
HTuple end_val75 = (hv_Keys.TupleLength())-1;
HTuple step_val75 = 1;
for (hv_Index=0; hv_Index.Continue(end_val75, step_val75); hv_Index += step_val75)
{
	//! 获取数据类型
    GetDictParam(hv_Divide, "key_data_type", HTuple(hv_Keys[hv_Index]), &hv_DataType);
    //! 获取数据值
    GetDictTuple(hv_Divide, HTuple(hv_Keys[hv_Index]), &hv_Value);
}

9.HTuple字典元组数据遍历

cpp 复制代码
GetDictTuple(hv_DictHandle, "TrainingModel", &hv_TrainingModel);
qDebug()<<"hv_TrainingModel: "<<(int)hv_TrainingModel.TupleLength();
for (int i = 0; i < hv_TrainingModel.TupleLength(); i++)
{
   HTuple TrainingModel=hv_TrainingModel[i];
}

10.Tuple 数据转换 QString,int,Double

从Tuple数据类型转换成QT中常用的数据类型,
如果Tuple中的数据类型与你转换的数据类型不一致,会导致异常需要注意

cpp 复制代码
QString Train_Name=QString::fromUtf8(hv_DictHandle.TupleGetDictTuple("Train_Name").S());
int Channels=hv_DictHandle.TupleGetDictTuple("Channels").I();
double num_epochs=hv_DictHandle.TupleGetDictTuple("num_epochs").D();

二、QDataSteam序列化与反序列化结构体

一开始我是在项目中使用Tuple 字典保存项目结构,这样也能保存训练的数据和模型数据,而且Tuple自带线程安全,哪怕是在改都可以。

但是当告诉我软件需要兼容其他深度训练框架的时候,就不太适用了

就必须使用结构体来保存项目结构了,这意味着软件后期需要大改,淦。

(╯°Д°)╯︵ ┻━┻

于是仔细研究了下QDataSteam序列化与反序列化结构体,争取尽量减少改动,

于是整理了一下具体实现,┬─┬ ノ('-'ノ)

至于为什么不用sqlite或xml,json来保存...

因为用得多了显得捞...

1.定义一个复杂的结构体

定义一个多个数据,嵌套其他结构的结构体 DictHandData :

用来模拟实际项目的复杂结构。

cpp 复制代码
struct MapDepot
{
    int     image_id;
    QString image_file_name;
    int     image_label_id;
    QString split;
};

struct Classes
{
    QString class_names;
    int     class_ids;
    QString class_color;
    QString shortcutkey;
};

struct Splits
{
    QString split_name;
    int     train_num;
    int     train_percentum;
    int     validation_num;
    int     validation_percentum;
    int     test_num;
    int     test_percentum;
};

struct TrainInfo
{
    double  epoch;
    double  num_epochs;
    double  num_iterations_per_epoch;
    double  mean_loss;
    int     mean_loss_samples;
    int     start_epoch;
    double  start_time;
    double  time_elapsed;
};

struct XProgres
{
    QString Natural_Model_Path;
    QString ExampleDataDir;
    QString DL_Dataset;
    QString DL_Preprocess_Param;
    QString Current_State;
    QString Operating_State;
    QList<TrainInfo> TrainInfos;
};

struct Trains
{
    QString Train_Name;
    QString Natural_Model;
    int     Image_Width;
    int     Image_Height;
    int     Channels;
    QString Facility_Name;
    int     Seed_Rand;
    int     Num_Epochs;
    int     Num_Batch;
    int     Num_Iterations;
    double  Learning_Rate;
    QString Correlation_Splitting;
    QString Current_State;
    QString Operating_State;
    int     Current_Schedule;
    QString Current_Assessment;

    XProgres Progres;
};



//! 自定义多重结构体
struct DictHandData
{
    int ProjectType;
    QString ProjectName;
    QString ProjectPath;
    QString ProjectDir;
    QString ProjectNode;

    //! 图元集合
    QList<MapDepot> MapDepotLists;
    QList<Classes>  ClassessLists;
    QList<Splits>   SplitItems;
    QList<Trains>   TrainingModel;

};

2.重写operator <<和>>操作符

通过重写operator <<operator >>操作符实现结构体的序列化与反序列化:

注意:操作符函数声明为 inline,防止多重定义:

看着写的多,实际上千篇一律,按照顺序输出,写入就行了。

cpp 复制代码
//! 操作符函数声明为 inline,防止多重定义:
//! 定义写入MapDepot
inline QDataStream& operator<<(QDataStream& out, const MapDepot& config) {
    out << config.image_id << config.image_file_name
        << config.image_label_id << config.split;
    return out;
}

//! 定义读取MapDepot
inline QDataStream& operator>>(QDataStream& in, MapDepot& config) {
    in >> config.image_id >> config.image_file_name
        >> config.image_label_id >> config.split;
    return in;
}

//! 定义写入 Classes
inline QDataStream& operator<<(QDataStream& out, const Classes& config) {
    out << config.class_names << config.class_ids
        << config.class_color << config.shortcutkey;
    return out;
}

//! 定义读取 Classes
inline QDataStream& operator>>(QDataStream& in, Classes& config) {
    in >> config.class_names >> config.class_ids
        >> config.class_color >> config.shortcutkey;
    return in;
}

//! 定义写入 Splits
inline QDataStream& operator<<(QDataStream& out, const Splits& config) {
    out << config.split_name
        << config.train_num << config.train_percentum
        << config.validation_num << config.validation_percentum
        << config.test_num << config.test_percentum;
    return out;
}

//! 定义读取 Splits
inline QDataStream& operator>>(QDataStream& in, Splits& config) {
    in >> config.split_name
        >> config.train_num >> config.train_percentum
        >> config.validation_num >> config.validation_percentum
        >> config.test_num >> config.test_percentum;
    return in;
}

//! 定义写入 TrainInfo
inline QDataStream& operator<<(QDataStream& out, const TrainInfo& config) {
    out << config.epoch<< config.num_epochs
        << config.num_iterations_per_epoch << config.mean_loss
        << config.mean_loss_samples << config.start_epoch
        << config.start_time << config.time_elapsed;
    return out;
}

//! 定义读取 TrainInfo
inline QDataStream& operator>>(QDataStream& in, TrainInfo& config) {
    in >> config.epoch >> config.num_epochs
        >> config.num_iterations_per_epoch >> config.mean_loss
        >> config.mean_loss_samples >> config.start_epoch
        >> config.start_time >> config.time_elapsed;
    return in;
}

//! 定义写入 XProgres
inline QDataStream& operator<<(QDataStream& out, const XProgres& config) {
    out << config.Natural_Model_Path<< config.ExampleDataDir
        << config.DL_Dataset << config.DL_Preprocess_Param
        << config.Current_State << config.Operating_State
        << config.TrainInfos;
    return out;
}

//! 定义读取 XProgres
inline QDataStream& operator>>(QDataStream& in, XProgres& config) {
    in >> config.Natural_Model_Path >> config.ExampleDataDir
        >> config.DL_Dataset >> config.DL_Preprocess_Param
        >> config.Current_State >> config.Operating_State
        >> config.TrainInfos;
    return in;
}


//! 定义写入 Trains
inline QDataStream& operator<<(QDataStream& out, const Trains& config) {
    out << config.Train_Name<< config.Natural_Model
        << config.Image_Width << config.Image_Height
        << config.Channels << config.Facility_Name
        << config.Seed_Rand << config.Num_Epochs
        << config.Num_Batch << config.Num_Iterations
        << config.Learning_Rate << config.Correlation_Splitting
        << config.Current_State << config.Operating_State
        << config.Current_Schedule << config.Current_Assessment
        << config.Progres;
    return out;
}

//! 定义读取 Trains
inline QDataStream& operator>>(QDataStream& in, Trains& config) {
    in  >> config.Train_Name >> config.Natural_Model
        >> config.Image_Width >> config.Image_Height
        >> config.Channels >> config.Facility_Name
        >> config.Seed_Rand >> config.Num_Epochs
        >> config.Num_Batch >> config.Num_Iterations
        >> config.Learning_Rate >> config.Correlation_Splitting
        >> config.Current_State >> config.Operating_State
        >> config.Current_Schedule >> config.Current_Assessment
        >> config.Progres;
    return in;
}


//! 定义写入 DictHandData
inline QDataStream& operator<<(QDataStream& out, const DictHandData& config) {
    out << config.ProjectType<< config.ProjectName
        << config.ProjectPath << config.ProjectDir
        << config.ProjectNode << config.MapDepotLists
        << config.ClassessLists << config.SplitItems
        << config.TrainingModel;
    return out;
}

//! 定义读取 DictHandData
inline QDataStream& operator>>(QDataStream& in, DictHandData& config) {
    in  >> config.ProjectType >> config.ProjectName
        >> config.ProjectPath >> config.ProjectDir
        >> config.ProjectNode >> config.MapDepotLists
        >> config.ClassessLists >> config.SplitItems
        >> config.TrainingModel;
    return in;
}

而通过这种方式写入保存的数据,在txt文本中依旧能看到具体的文件路径或名称,这得修改一下,至少内容不可见。

2.从新修改operator 操作符 使用Base64简单加密字符串

使用Base64和utf8简单加密字符串防止出现具体内容。

甚至可以使用其他的加密库实现.这里只介绍了最简单的用法

cpp 复制代码
//! 使用Base64加密
//! 操作符函数声明为 inline,防止多重定义:
//! 定义写入MapDepot
inline QDataStream& operator<<(QDataStream& out, const MapDepot& config) {
    out << config.image_id << config.image_file_name.toUtf8().toBase64()
        << config.image_label_id << config.split.toUtf8().toBase64();
    return out;
}

//! 定义读取MapDepot
inline QDataStream& operator>>(QDataStream& in, MapDepot& config) {
    QByteArray image_file_name;
    QByteArray split;
    in >> config.image_id >> image_file_name
        >> config.image_label_id >> split;
    config.image_file_name=QString::fromUtf8(QByteArray::fromBase64(image_file_name));
    config.split=QString::fromUtf8(QByteArray::fromBase64(split));
    return in;
}

//! 定义写入 Classes
inline QDataStream& operator<<(QDataStream& out, const Classes& config) {
    out << config.class_names.toUtf8().toBase64() << config.class_ids
        << config.class_color.toUtf8().toBase64() << config.shortcutkey.toUtf8().toBase64();
    return out;
}

//! 定义读取 Classes
inline QDataStream& operator>>(QDataStream& in, Classes& config) {
    QByteArray class_names;
    QByteArray class_color;
    QByteArray shortcutkey;
    in >> class_names >> config.class_ids
        >> class_color >> shortcutkey;

    config.class_names=QString::fromUtf8(QByteArray::fromBase64(class_names));
    config.class_color=QString::fromUtf8(QByteArray::fromBase64(class_color));
    config.shortcutkey=QString::fromUtf8(QByteArray::fromBase64(shortcutkey));
    return in;
}

//! 定义写入 Splits
inline QDataStream& operator<<(QDataStream& out, const Splits& config) {
    out << config.split_name.toUtf8().toBase64()
        << config.train_num << config.train_percentum
        << config.validation_num << config.validation_percentum
        << config.test_num << config.test_percentum;
    return out;
}

//! 定义读取 Splits
inline QDataStream& operator>>(QDataStream& in, Splits& config) {
       QByteArray split_name;

    in >> split_name
        >> config.train_num >> config.train_percentum
        >> config.validation_num >> config.validation_percentum
        >> config.test_num >> config.test_percentum;

       config.split_name=QString::fromUtf8(QByteArray::fromBase64(split_name));
    return in;
}

//! 定义写入 TrainInfo
inline QDataStream& operator<<(QDataStream& out, const TrainInfo& config) {
    out << config.epoch<< config.num_epochs
        << config.num_iterations_per_epoch << config.mean_loss
        << config.mean_loss_samples << config.start_epoch
        << config.start_time << config.time_elapsed;
    return out;
}

//! 定义读取 TrainInfo
inline QDataStream& operator>>(QDataStream& in, TrainInfo& config) {
    in >> config.epoch >> config.num_epochs
        >> config.num_iterations_per_epoch >> config.mean_loss
        >> config.mean_loss_samples >> config.start_epoch
        >> config.start_time >> config.time_elapsed;
    return in;
}

//! 定义写入 XProgres
inline QDataStream& operator<<(QDataStream& out, const XProgres& config) {
    out << config.Natural_Model_Path.toUtf8().toBase64()<< config.ExampleDataDir.toUtf8().toBase64()
        << config.DL_Dataset.toUtf8().toBase64() << config.DL_Preprocess_Param.toUtf8().toBase64()
        << config.Current_State.toUtf8().toBase64() << config.Operating_State.toUtf8().toBase64()
        << config.TrainInfos;
    return out;
}

//! 定义读取 XProgres
inline QDataStream& operator>>(QDataStream& in, XProgres& config) {
    QByteArray Natural_Model_Path;
    QByteArray ExampleDataDir;
    QByteArray DL_Dataset;
    QByteArray DL_Preprocess_Param;
    QByteArray Current_State;
    QByteArray Operating_State;
    in >> Natural_Model_Path >> ExampleDataDir
        >> DL_Dataset >> DL_Preprocess_Param
        >> Current_State >> Operating_State
        >> config.TrainInfos;

    config.Natural_Model_Path=QString::fromUtf8(QByteArray::fromBase64(Natural_Model_Path));
    config.ExampleDataDir=QString::fromUtf8(QByteArray::fromBase64(ExampleDataDir));
    config.DL_Dataset=QString::fromUtf8(QByteArray::fromBase64(DL_Dataset));
    config.DL_Preprocess_Param=QString::fromUtf8(QByteArray::fromBase64(DL_Preprocess_Param));
    config.Current_State=QString::fromUtf8(QByteArray::fromBase64(Current_State));
    config.Operating_State=QString::fromUtf8(QByteArray::fromBase64(Operating_State));
    return in;
}


//! 定义写入 Trains
inline QDataStream& operator<<(QDataStream& out, const Trains& config) {
    out << config.Train_Name.toUtf8().toBase64()<< config.Natural_Model.toUtf8().toBase64()
        << config.Image_Width << config.Image_Height
        << config.Channels << config.Facility_Name.toUtf8().toBase64()
        << config.Seed_Rand << config.Num_Epochs
        << config.Num_Batch << config.Num_Iterations
        << config.Learning_Rate << config.Correlation_Splitting.toUtf8().toBase64()
        << config.Current_State.toUtf8().toBase64() << config.Operating_State.toUtf8().toBase64()
        << config.Current_Schedule << config.Current_Assessment.toUtf8().toBase64()
        << config.Progres;
    return out;
}

//! 定义读取 Trains
inline QDataStream& operator>>(QDataStream& in, Trains& config) {
    QByteArray Train_Name;
    QByteArray Natural_Model;
    QByteArray Facility_Name;
    QByteArray Correlation_Splitting;
    QByteArray Current_State;
    QByteArray Operating_State;
    QByteArray Current_Assessment;
    in  >> Train_Name >> Natural_Model
        >> config.Image_Width >> config.Image_Height
        >> config.Channels >> Facility_Name
        >> config.Seed_Rand >> config.Num_Epochs
        >> config.Num_Batch >> config.Num_Iterations
        >> config.Learning_Rate >> Correlation_Splitting
        >> Current_State >> Operating_State
        >> config.Current_Schedule >> Current_Assessment
        >> config.Progres;

    config.Train_Name=QString::fromUtf8(QByteArray::fromBase64(Train_Name));
    config.Natural_Model=QString::fromUtf8(QByteArray::fromBase64(Natural_Model));
    config.Facility_Name=QString::fromUtf8(QByteArray::fromBase64(Facility_Name));
    config.Correlation_Splitting=QString::fromUtf8(QByteArray::fromBase64(Correlation_Splitting));
    config.Current_State=QString::fromUtf8(QByteArray::fromBase64(Current_State));
    config.Operating_State=QString::fromUtf8(QByteArray::fromBase64(Operating_State));
    config.Current_Assessment=QString::fromUtf8(QByteArray::fromBase64(Current_Assessment));
    return in;
}


//! 定义写入 DictHandData
inline QDataStream& operator<<(QDataStream& out, const DictHandData& config) {
    out << config.ProjectType<< config.ProjectName.toUtf8().toBase64()
        << config.ProjectPath.toUtf8().toBase64() << config.ProjectDir.toUtf8().toBase64()
        << config.ProjectNode.toUtf8().toBase64() << config.MapDepotLists
        << config.ClassessLists << config.SplitItems
        << config.TrainingModel;
    return out;
}

//! 定义读取 DictHandData
inline QDataStream& operator>>(QDataStream& in, DictHandData& config) {
    QByteArray ProjectName;
    QByteArray ProjectPath;
    QByteArray ProjectDir;
    QByteArray ProjectNode;

    in  >> config.ProjectType >> ProjectName
        >> ProjectPath >> ProjectDir
        >> ProjectNode >> config.MapDepotLists
        >> config.ClassessLists >> config.SplitItems
        >> config.TrainingModel;

    config.ProjectName=QString::fromUtf8(QByteArray::fromBase64(ProjectName));
    config.ProjectPath=QString::fromUtf8(QByteArray::fromBase64(ProjectPath));
    config.ProjectDir=QString::fromUtf8(QByteArray::fromBase64(ProjectDir));
    config.ProjectNode=QString::fromUtf8(QByteArray::fromBase64(ProjectNode));
    return in;
}

#endif

使用 QDataSteam 序列化结构体

使用 QDataSteam 序列化结构体快速写入文本文件中:

cpp 复制代码
 	QFile file("HandDatas.txt");
 	DictHandData HandDatas;
 	//! 确保HandDatas结构体有数据
    if (file.open(QIODevice::WriteOnly)) {
        QDataStream out(&file);
        out.setByteOrder(QDataStream::BigEndian);
        out.setVersion(QDataStream::Qt_5_13);
        out<<HandDatas;
        file.close();
    }

使用 QDataSteam 反序列化结构体

使用 QDataSteam 从文件中加载结构体数据:

cpp 复制代码
 	QFile file("HandDatas.txt");
 	DictHandData HandDatas;
    if (file.open(QIODevice::ReadOnly)) {

        QDataStream out(&file);
        out.setByteOrder(QDataStream::BigEndian);
        out.setVersion(QDataStream::Qt_5_13);
        out>>HandDatas;
        file.close();
    }

简单,快速,高效!

三、其他

1.重写QDebug& operator<<操作符,打印结构体

为了快速的验证数据经过序列化和反序列化之后有没有问题,

于是又重写 inline QDebug& operator<<(QDebug& out, const 结构体& config)方法

实现直接qDebug()i打印结构体中的数据。

cpp 复制代码
//! 定义打印输出
inline QDebug& operator<<(QDebug& out, const MapDepot& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "MapDepot("
        << "\n  image_id: " << config.image_id
        << "\n  image_file_name: " << config.image_file_name
        << "\n  image_label_id: " << config.image_label_id
        << "\n  split: " << config.split
        << "\n)";
    return out;
}

inline QDebug& operator<<(QDebug& out, const Classes& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "Classes("
        << "\n  class_names: " << config.class_names
        << "\n  class_ids: " << config.class_ids
        << "\n  class_color: " << config.class_color
        << "\n  shortcutkey: " << config.shortcutkey
        << "\n)";
    return out;
}

inline QDebug& operator<<(QDebug& out, const Splits& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "Splits("
        << "\n  split_name: " << config.split_name
        << "\n  train_num: " << config.train_num
        << "\n  train_percentum: " << config.train_percentum
        << "\n  validation_num: " << config.validation_num
        << "\n  validation_percentum: " << config.validation_percentum
        << "\n  test_num: " << config.test_num
        << "\n  test_percentum: " << config.test_percentum
        << "\n)";
    return out;
}

inline QDebug& operator<<(QDebug& out, const TrainInfo& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "TrainInfo("
        << "\n  epoch: " << config.epoch
        << "\n  num_epochs: " << config.num_epochs
        << "\n  num_iterations_per_epoch: " << config.num_iterations_per_epoch
        << "\n  mean_loss: " << config.mean_loss
        << "\n  mean_loss_samples: " << config.mean_loss_samples
        << "\n  start_epoch: " << config.start_epoch
        << "\n  start_time: " << config.start_time
        << "\n  time_elapsed: " << config.time_elapsed
        << "\n)";
    return out;
}


inline QDebug& operator<<(QDebug& out, const XProgres& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "XProgres("
        << "\n  Natural_Model_Path: " << config.Natural_Model_Path
        << "\n  ExampleDataDir: " << config.ExampleDataDir
        << "\n  DL_Dataset: " << config.DL_Dataset
        << "\n  DL_Preprocess_Param: " << config.DL_Preprocess_Param
        << "\n  Current_State: " << config.Current_State
        << "\n  Operating_State: " << config.Operating_State
        << "\n  TrainInfos: " << config.TrainInfos
        << "\n)";
    return out;
}


inline QDebug& operator<<(QDebug& out, const Trains& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "Trains("
        << "\n  Train_Name: " << config.Train_Name
        << "\n  Natural_Model: " << config.Natural_Model
        << "\n  Image_Width: " << config.Image_Width
        << "\n  Image_Height: " << config.Image_Height
        << "\n  Channels: " << config.Channels
        << "\n  Facility_Name: " << config.Facility_Name
        << "\n  Seed_Rand: " << config.Seed_Rand
        << "\n  Num_Epochs: " << config.Num_Epochs
        << "\n  Num_Batch: " << config.Num_Batch
        << "\n  Num_Iterations: " << config.Num_Iterations
        << "\n  Learning_Rate: " << config.Learning_Rate
        << "\n  Correlation_Splitting: " << config.Correlation_Splitting
        << "\n  Current_State: " << config.Current_State
        << "\n  Operating_State: " << config.Operating_State
        << "\n  Current_Schedule: " << config.Current_Schedule
        << "\n  Current_Assessment: " << config.Current_Assessment
        << "\n  Progres: " << config.Progres
        << "\n)";
    return out;
}

inline QDebug& operator<<(QDebug& out, const DictHandData& config) {
    QDebugStateSaver saver(out);  // 保存调试状态
    out.nospace();  // 禁止自动添加空格

    out << "DictHandData("
        << "\n  ProjectType: " << config.ProjectType
        << "\n  ProjectName: " << config.ProjectName
        << "\n  ProjectPath: " << config.ProjectPath
        << "\n  ProjectDir: " << config.ProjectDir
        << "\n  ProjectNode: " << config.ProjectNode
        << "\n  MapDepotLists: " << config.MapDepotLists
        << "\n  ClassessLists: " << config.ClassessLists
        << "\n  SplitItems: " << config.SplitItems
        << "\n  TrainingModel: " << config.TrainingModel
        << "\n)";
    return out;
}

调用

打印所有数据

cpp 复制代码
    //!同HTuple字典数据字段 结构体
    DictHandData HandDatas;
   	qDebug()<<" <- DictHandData -> ";
    qDebug().noquote() <<HandDatas;

总结

通过QDataSteam序列化与反序列化项目结构体,能最大的减少当结构体发生改变的时候,重新修改加载和保存函数。减少工作量。

相关推荐
世转神风-3 小时前
qt-基础打印-不换行打印
开发语言·qt
老歌老听老掉牙3 小时前
PyQt5中RadioButton互斥选择的实现方法
开发语言·python·qt
864记忆5 小时前
Qt Creator 常用命令的中英文对照表
开发语言·qt
Larry_Yanan6 小时前
Qt多进程(六)共享内存和信号量
开发语言·qt
东方忘忧6 小时前
Qt使用QDesktopServices::openUrl打开系统默认应用(如浏览器,文件,文件夹和邮件)
开发语言·qt
计算机内卷的N天6 小时前
qt的模态和非模态状态
开发语言·qt
charlie071 天前
qmake工程不能显示手动配置的Kit
qt
深蓝海拓1 天前
PySide6从0开始学习的笔记(二十) qdarkstyle的深入应用
笔记·python·qt·学习·pyqt
世转神风-1 天前
qt-通信协议基础-double转成QbyteArray-小端系统
开发语言·qt