- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试序列化自定义类 Layer*
并使用 QDataStream 读回。现在,Layer
是一个具有虚方法的抽象类,由不同类型的层继承:RasterLayer
, TextLayer
, AdjustmentLayer
等
我有一个 QList<Layer*> layers
它跟踪所有图层,并且对图层所做的任何调整都会在列表中更新。我需要将 QList 序列化和反序列化到其原始状态,并恢复各个层(不同类型)的属性。
这是layer.h:
#ifndef LAYER_H
#define LAYER_H
#include <QString>
#include <QImage>
#include <QDebug>
#include <QListWidgetItem>
#include <QGraphicsItem>
#include <QPixmap>
class Layer : public QListWidgetItem
{
public:
enum LayerType{
RASTER,
VECTOR,
TEXT,
ADJUSTMENT
};
Layer(QString name, LayerType type);
~Layer();
inline void setName(QString &name) { _name = name; }
inline QString getName() { return _name; }
inline LayerType getType() { return _type; }
virtual void setSceneSelected(bool select) = 0;
virtual void setLayerSelected(bool select) = 0;
virtual void setZvalue(int z) = 0;
virtual void setParent(QGraphicsItem *parent) = 0;
protected:
QString _name;
LayerType _type;
};
#endif // LAYER_H
这是由 RasterLayer 类扩展的:
#ifndef RASTERLAYER_H
#define RASTERLAYER_H
#include <QGraphicsPixmapItem>
#include <QPainter>
#include <QGraphicsScene>
#include "layer.h"
class RasterLayer : public Layer, public QGraphicsPixmapItem
{
public:
RasterLayer(const QString &name, const QImage &image);
RasterLayer();
~RasterLayer();
void setLocked(bool lock);
void setSceneSelected(bool select);
void setLayerSelected(bool select);
void setZvalue(int z);
void setParent(QGraphicsItem *parent);
inline QPixmap getPixmap() const { return pixmap(); }
inline QPointF getPos() const { return QGraphicsPixmapItem::pos(); }
inline void setLayerPos(QPointF pos) { setPos(pos);}
inline void setLayerPixmap(QPixmap pixmap) { setPixmap(pixmap); }
friend QDataStream& operator<<(QDataStream& ds, RasterLayer *&layer)
{
ds << layer->getPixmap() << layer->getName() << layer->getPos();
return ds;
}
friend QDataStream& operator>>(QDataStream& ds, RasterLayer *layer)
{
QString name;
QPixmap pixmap;
QPointF pos;
ds >> pixmap >> name >> pos;
layer->setName(name);
layer->setPixmap(pixmap);
layer->setPos(pos);
return ds;
}
protected:
void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget);
private:
QImage _image;
};
#endif // RASTERLAYER_H
我目前正在尝试测试 RasterLayer
的序列化-反序列化像这样:
QFile file(fileName);
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
Layer *layer = paintWidget->getItems().at(1);
// Gets the second element in the list
RasterLayer *raster = dynamic_cast<RasterLayer*> (layer);
out << raster;
file.close();
现在,正如你在这里看到的,我特别转换 Layer*
到 RasterLayer*
进行序列化,这是可行的,因为到目前为止我只处理过一种类型的图层。所以我的第一个问题是:
我如何将这个序列化过程推广到所有类型的层?
每种类型的图层都有不同的序列化方式,因为每个图层都具有不同的属性。此外,这里的转换感觉有点代码味道,而且可能是糟糕的设计选择。因此,预期的场景是序列化整个层列表并调用其相应的重载运算符。
我的第二个问题是:
如何正确反序列化数据?这是我目前如何序列化个人 RasterLayer
:
QFile newFile(fileName);
newFile.open(QIODevice::ReadOnly);
QDataStream in(&newFile);
RasterLayer *layer2 = new RasterLayer;
in >> layer2;
paintWidget->pushLayer(layer2);
ui->layerView->updateItems(paintWidget->getItems());
首先,我认为在这种情况下我不应该将序列化为指针,但我不确定还可以做什么或如何做得更好。其次,反序列化在这里起作用,但它并没有完全按照我的预期进行。尽管我在重载运算符中使用了 setter,但它确实没有正确更新图层。我需要调用构造函数来从中创建一个新层。
我试过这个:Serialization with Qt但我不太确定如何获得 Layer*
将其转换为 Layer
,对其进行序列化、反序列化,然后将其转换回 Layer*
.所以我需要添加第三步:
RasterLayer *layer3 = new RasterLayer(layer2->getName(), layer2->getPixmap().toImage());
layer3->setPos(layer2->pos());
然后按layer3
到列表以使其真正起作用。根据这篇文章:https://stackoverflow.com/a/23697747/6109408 ,我真的不应该做 new RasterLayer...
在运算符重载函数中(否则我会在 hell 里煎熬),我遵循那里给出的第一个建议,这对我来说不是很有效,我不知道正确的方法。
此外,我如何将其反序列化为 Layer*
的一般 QList?而不是必须创建新的特定层实例并向它们注入(inject)反序列化数据?虽然这很相似:Serialize a class with a Qlist of custom classes as member (using QDataStream) ,答案不够清楚,我无法理解。
我有一个关于中间值持有者类的想法,我将使用它来序列化各种层,并让它根据层的类型创建和注入(inject)参数,但我不确定这是否可行.
谢谢你帮助我。
最佳答案
我希望下面的例子能给你一个大概的概念:
#include <iostream>
#include <fstream>
#include <list>
class A{
int a=0;
public:
virtual int type(){return 0;}
virtual void serialize(std::ostream& stream)const{
stream<<a<<std::endl;
}
virtual void deserialize(std::istream& stream){
stream>>a;
}
friend std::ostream& operator <<(std::ostream& stream, const A& object){
object.serialize(stream);
return stream;
}
friend std::istream& operator >>(std::istream& stream, A& object){
object.deserialize(stream);
return stream;
}
virtual ~A(){}
};
class B : public A{
int b=1;
public:
virtual int type(){return 1;}
virtual void serialize(std::ostream& stream)const{
A::serialize(stream);
stream<<b<<std::endl;
}
virtual void deserialize(std::istream& stream){
A::deserialize(stream);
stream>>b;
}
};
class C : public A{
int c=2;
public:
virtual int type(){return 2;}
virtual void serialize(std::ostream& stream)const{
A::serialize(stream);
stream<<c<<std::endl;
}
virtual void deserialize(std::istream& stream){
A::deserialize(stream);
stream>>c;
}
};
std::ostream& operator <<(std::ostream& stream, const std::list<A*>& l){
stream<<l.size()<<std::endl;
for(auto& a_ptr: l){
stream<<a_ptr->type()<<std::endl;
stream<<*a_ptr;
}
}
std::istream& operator >>(std::istream& stream, std::list<A*>& l){
l.clear();
int size, type;
stream>>size;
A* tmp;
for(int i =0; i<size; ++i){
stream>>type;
if(type==0){
tmp = new A;
}
if(type==1){
tmp = new B;
}
if(type==2){
tmp = new C;
}
stream>>(*tmp);
l.push_back(tmp);
}
return stream;
}
int main(){
A* a = new A;
A* b = new B;
A* c = new C;
std::list<A*> List{ a, b, c };
std::list<A*> List2;
std::ofstream ofs("D:\\temp.txt");
ofs<<List;
ofs.flush();
ofs.close();
std::ifstream ifs("D:\\temp.txt");
ifs>>List2;
std::cout<<List2;
for(auto& a_ptr : List2){
delete a_ptr;
}
delete c;
delete b;
delete a;
return 0;
}
编辑:我没有考虑到在序列化列表时我们应该写列表的大小和元素的类型才能成功反序列化,所以我修改了示例。
关于c++ - 如何使用 QDatastream 在 QT 中正确序列化和反序列化 QList 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51403419/
我有一个相当奇怪的问题,使用 QDataStream,或者至少对我来说很奇怪,因为我根本不理解这种行为。 当然,我的问题来自一个大项目,但我设法用一个最小的例子重现了这种奇怪的行为,我现在将对此进行描
QFile msnLogFile(item->data(Qt::UserRole).toString()); QDataStream logDataStream; if(msnLogFile
我有一个包含两个主要模块的应用程序。一个是用 C 编写的,使用标准 C 运行时库,另一个是用 Qt C++ 编写的。它们通过 IPC 相互通信。 C 模块创建一个 char 数组,用数据填充它并发送到
我正在努力学习教程 here并序列化 Qt 对象。这是我的代码: QFile file("/Users/kaustav/Desktop/boo.dat"); if (!file.open(QIODev
我想将 QVector 序列化为 char* 数组。我通过以下代码执行此操作: QVector in; ... QByteArray bytes; QDataStream stream(&bytes,
我正在尝试保存 3 QVector和一个带有 QDataStream 的整数. 我重载了 operator #include #include class CloudData { public:
我正在尝试将特征向量序列化为 QDataStream: #include "utils.h" #include "Eigen/Eigen" int main(int argc, char *argv[
我正在用 Qt 实现一个小接口(interface)。在我目前正在处理的步骤中,我有 Scores(自定义类)我可以在只能容纳一个 Score 的 Docks(同样是自定义类)上移动。 我用这个例子启
假设我有一个创建 QIODevice(例如 QFile)的函数,然后返回一个指向从 QIODevice 构造的 QDataStream 的指针。在这里处理内存分配的最佳方法是什么?显然,QIODevi
我需要通过 QTcpSocket 接收二进制数据(读取浮点数)并使用 QDatastream 将它们写入 Qfile。但是我在使用 QDataStream 时遇到了一些问题。如下,我只能用这种方式来实
请考虑以下来自 QDataStream 的代码片段文档: QFile file("file.dat"); file.open(QIODevice::ReadOnly); QDataStream in(
我目前正在尝试在我的代码中实现一个序列化系统,该系统将一个类型的多个对象存储在一个文件中。这非常有效,我通常只是使用 OpenMode QIODevice::Append 将它们一一附加。这里没有问题
我想将存储在 vector (保存结构)中的数据写入文件,并从该文件读取数据。我尝试使用 QDataStream 并重载“>>”和“ &data) { for(uint8_t i=0; i >
我想为抽象类重载 class AbstractBaseClass { public: AbstractBaseClass(); int BaseFirstField() const;
我正在尝试在 QTcpSocket 上发送一个 QByteArray 。我面临的问题是,虽然我发送了一个长度为 25 的数组,但在服务器上它收到了 59 个字节。这是我的示例代码: //client
这是一个关于在 C++ 和 Linux 中使用 QDataStream 和 QTemporaryFile 的 QT 问题。 我在刷新 QDataStream 时遇到了一些问题。 QTextStream
我正在 Qt 中编写一个简单的基于 TCP 的网络应用程序并想使用 QDataStream和 QByteArray通过网络发送数据。问题是当我将数据放入 QByteArray 时他们被“归零”了。例如
我有来自 tcp 套接字的数据作为原始数据(我有指定的格式),然后基于该数据创建一个对象。格式是这样的:24 字节的 header [数据大小和一些其他信息],然后是 header 中指定的数据量。
我有一个文件,假设长度为 8 个字节。例如它看起来像这样: 22222222 现在,我先读取 5 个字节并更改它们。对于前。到 11111 最后,我想将它们写入 ONTO EXCISTING DATA
根据本网站上的各种答案,我尝试定义自己的模板函数以将任何枚举值写入 QDataStream。 template ::value>> QDataStream &operator>(enumValue);
我是一名优秀的程序员,十分优秀!