使用带有 QDataStream 的自定义 QMetaType

Posted

技术标签:

【中文标题】使用带有 QDataStream 的自定义 QMetaType【英文标题】:using custom QMetaType with QDataStream 【发布时间】:2018-05-18 19:51:37 【问题描述】:

我正在尝试使用 QDataStream 对象加载和存储自定义 QMetaType。这是一个例子:

int main(int argc, char *argv[])

    QApplication a(argc, argv);
    QString test1("/test1/");
    const QString path1(QDir::homePath()+test1);
    qDebug() << "path1 variable is " << path1;
    QDir apphome(path1);
    qDebug() << "apphome path is " << apphome.absolutePath();
    if (!apphome.mkdir(path1))  qDebug() << "mkdir returned false. directory already exists?"; 
    if(!apphome.setCurrent(path1))  qDebug() << "did not set current directory"; 
    qDebug() << "apphome path is " << apphome.absolutePath();
    Basic basic1;
    Basic basic2;
    basic1.value = 14;
    QFile file1("file1name");
    if (!file1.open(QIODevice::WriteOnly))  qDebug() << "file1 not open."; 
    QDataStream dataStream1(&file1);
    QVariant qvar1;
    qvar1.setValue(basic1);
    dataStream1 << (quint32)12345;
    dataStream1 << qvar1;
    file1.close();
    file1.open(QIODevice::ReadOnly);
    QDataStream dataStream2(&file1);
    quint32 magic;
    QVariant qvar2;
    dataStream1 >> magic;
    qDebug() << "magic number is " << magic;
    dataStream2 >> qvar2;
    file1.close();
    basic2 = qvar2.value<Basic>();
    qDebug() << "14 = " << basic1.value << " = " << basic2.value << ".";

    //MainWindow w;
    //w.show();

    return a.exec();

幻数又回来了,但有一条消息QVariant::save: unable to save type 'Basic' (type id: 1026).,当然还有QVariant::load: unable to load type 1026.,然后是14 = 14 = 0。 Basic 类仅来自 QMetaType 文档:

struct Basic

    Basic();
    Basic(const Basic &basic);
    ~Basic();
    int value;
;
Q_DECLARE_METATYPE(Basic)

// basic.cpp

#include "basic.h"

Basic::Basic() 

Basic::Basic(const Basic &basic)

    value = basic.value;


Basic::~Basic()

我的想法不多了,有人知道导致问题的原因吗? Qt的版本是5.10.1。

【问题讨论】:

您没有实现流式传输。也是重复的 真的有问题吗?我认为这是自动处理的。文档中的任何地方都没有提到它。 对于某些内置支持的类型,是的,QVariant会这样做(直接实现),否则它会调用该运算符或打印这些消息。这不是 LUA 或 java,因此序列化不是在对象表示级别上自动进行的。有QSetting 相关问题归结为同一个问题。 更正:它*在文档中提到,但仅在 qRegisterMetaType 和 qRegisterMetaTypeStreamOperators 成员的描述下(如果我没记错的话)。 【参考方案1】:

因为编译器无法读懂您的想法,您需要描述如何进行序列化,例如

struct Basic

    Basic();
    Basic(const Basic &basic);
    ~Basic();
    int value;

    friend QDataStream & operator << (QDataStream &arch, const Basic& object)
    
        arch << object.value;
        return arch;
    

    friend QDataStream & operator >> (QDataStream &arch, Basic& object)
    
        arch >> object.value;
        return arch;
    
;
Q_DECLARE_METATYPE(Basic);

在main()中

qRegisterMetaType<Basic>("Basic");
qRegisterMetaTypeStreamOperators<Basic>("Basic");

在保存\加载操作发生之前。 Q_DECLARE_METATYPE 需要用 QVariant 来存储类型,这两个需要注册对象的“三巨头”来管理它作为资源及其序列化方法。输出:

path1 variable is  "C:/Users/Yaroslav/test1/"
apphome path is  "C:/Users/Yaroslav/test1"
mkdir returned false. directory already exists?
apphome path is  "C:/Users/Yaroslav/test1"
magic number is  12345
14 =  14  =  14 .

附:请注意,如果您在没有窗口的情况下离开 return a.exec();,您的程序将永远留在内存中,直到您停止它为止。

【讨论】:

@LuciusSchoenbaum 等等.. 你是这样做的.. 你忘记了一行。你忘记注册了 我注册了它,现在它可以工作了!谢谢你。 :)

以上是关于使用带有 QDataStream 的自定义 QMetaType的主要内容,如果未能解决你的问题,请参考以下文章

Qt QSharedMemory 和 QDataStream

使用 QDataStream 序列化自定义类导致 C2679 错误

使用带有 GuidedStepSupportFragment 的自定义 XML 布局进行智能电视 UI 设计

使用带有 TextField 的自定义表格视图单元格关闭数字键盘

带有实体框架的自定义函数

使用带有原型单元的自定义 UITableViewCell