[PyQt5-Node-Editor][进阶篇]使用Pyqt5制作节点编辑器(16)——序列化,保存Scene
2021/7/18 14:06:51
本文主要是介绍[PyQt5-Node-Editor][进阶篇]使用Pyqt5制作节点编辑器(16)——序列化,保存Scene,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
导航
- 目标
- 实现
- 建立一个序列化父模板
- Scene序列化
- Edge序列化
- Node序列化
- Socket序列化
- Content序列化
- View里保存和读取
目标
能够将scene数据保存为一个JSON文件,方便读取和保存
{ "id": 2586028185080, "scene_width": 64000, "scene_height": 64000, "node": [ { "id": 2586029654760, "title": "这是一个节点", "pos_x": -350.0, "pos_y": -250.0, "inputs": [ { "id": 2586029897152, "index": 0, "position": 2, "socket_type": 0 }, { "id": 2586029905288, "index": 1, "position": 2, "socket_type": 0 }, { "id": 2586029905344, "index": 2, "position": 2, "socket_type": 0 } ], "outputs": [ { "id": 2586029905400, "index": 0, "position": 3, "socket_type": 3 } ], "content": {} }, { "id": 2586029897096, "title": "这是第二个节点", "pos_x": -75.0, "pos_y": 0.0, "inputs": [ { "id": 2586029905512, "index": 0, "position": 2, "socket_type": 1 }, { "id": 2586029905568, "index": 1, "position": 2, "socket_type": 1 }, { "id": 2586029905624, "index": 2, "position": 2, "socket_type": 1 } ], "outputs": [ { "id": 2586029905680, "index": 0, "position": 3, "socket_type": 3 } ], "content": {} }, { "id": 2586029905456, "title": "这是第三个节点", "pos_x": 200.0, "pos_y": -150.0, "inputs": [ { "id": 2586029905792, "index": 0, "position": 2, "socket_type": 2 }, { "id": 2586029905848, "index": 1, "position": 2, "socket_type": 2 }, { "id": 2586029905904, "index": 2, "position": 2, "socket_type": 2 } ], "outputs": [ { "id": 2586029905960, "index": 0, "position": 3, "socket_type": 3 } ], "content": {} } ], "edges": [ { "id": 2586029905736, "edge_type": 2, "start": 2586029905400, "end": 2586029905512 }, { "id": 2586061985944, "edge_type": 2, "start": 2586029905680, "end": 2586029905904 } ] }
实现
建立一个序列化父模板
目前,我们建立了Node,Scene,Socket,Edge,Content这些类,
如果要想获取这些类的信息,存储到json文件里去,那么就需要这些类能够自己将自己的属性序列化
于是,我们可以写一个类来实现序列化功能,这个类作为父类,其他的类继承这个父类,并对其序列化操作进行改写
class Serializable(): def __init__(self): self.id = id(self) def serialize(self): raise NotImplemented() def deserialize(self, data, hashmap=[]): raise NotImplemented()
其中serialize用于编码,并返回编码,deserialize负责解码,deserialize的功能放在下一篇写
Scene序列化
我们将导入这三个包,并且让Scene继承Serializable
随后改写serialize,deserialize
def serialize(self): nodes, edges = [],[] for node in self.nodes: nodes.append(node.serialize()) for edge in self.edges: edges.append(edge.serialize()) return OrderedDict([ ('id',self.id), ('scene_width',self.scene_width), ('scene_height',self.scene_height), ('node',nodes), ('edges',edges), ]) def deserialize(self, data, hashmap=[]): print('解码数据', data) return False
Scene为最外层,node和edge是下一层,socket和content是node下的层
于是要获取node和edge的序列化信息,就需要调用
node.serialize()
edge.serialize()
除此之外,我将读取和保存的代码写在了Scene里
def saveToFile(self, filename): with open(filename, 'w') as file: file.write(json.dumps(self.serialize(), indent=4, ensure_ascii=False)) print(filename, "保存成功") def loadFromFlie(self, filename): with open(filename, 'r') as file: raw_data = file.read() data = json.loads(raw_data, encoding='utf-8') self.deserialize(data)
它将根据self.serialize()返回的值来保存JSON文件
Edge序列化
同理继承,后面都需要继承
def serialize(self): return OrderedDict([ ('id',self.id), ('edge_type', self.edge_type), ('start', self.start_socket.id), ('end', self.end_socket.id), ]) def deserialize(self, data, hashmap=[]): print('解码数据', data) return False
Node序列化
def serialize(self): inputs, outputs = [], [] for socket in self.inputs: inputs.append(socket.serialize()) for socket in self.outputs: outputs.append(socket.serialize()) return OrderedDict([ ('id', self.id), ('title', self.title), ('pos_x', self.grNode.scenePos().x()), ('pos_y', self.grNode.scenePos().y()), ('inputs', inputs), ('outputs', outputs), ('content', self.content.serialize()) ]) def deserialize(self, data, hashmap=[]): print('解码数据', data) return False
由于由于调用了
socket.serialize()
content.serialize()
来获取序列化信息,所以需要写他们两个的序列化
Socket序列化
def serialize(self): return OrderedDict([ ('id',self.id), ('index', self.index), ('position', self.position), ('socket_type', self.socket_type), ]) def deserialize(self, data, hashmap=[]): print('解码数据', data) return False
Content序列化
其中Content比较特殊,要继承Serializable,直接添加父类继承即可
def serialize(self): return OrderedDict([ ]) def deserialize(self, data, hashmap=[]): return False
这里我们只返回一个空列表,以后再来写
View里保存和读取
到View里的键入事件里,添加如下代码
def keyPressEvent(self, event): if event.key() == Qt.Key_Delete: if not self.editingFlag: self.deleteSelected() else: super().keyPressEvent(event) elif event.key() == Qt.Key_S and event.modifiers() & Qt.ControlModifier: self.grScene.scene.saveToFile('graph.json') elif event.key() == Qt.Key_L and event.modifiers() & Qt.ControlModifier: self.grScene.scene.loadFromFlie('graph.json') else: super().keyPressEvent(event)
按下Crtl+S保存,按下Crtl+L进行读取
保存后既可以看到目录下生成graph.json文件
这篇关于[PyQt5-Node-Editor][进阶篇]使用Pyqt5制作节点编辑器(16)——序列化,保存Scene的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-22怎么通过控制台去看我的页面渲染的内容在哪个文件中呢-icode9专业技术文章分享
- 2024-12-22el-tabs 组件只被引用了一次,但有时会渲染两次是什么原因?-icode9专业技术文章分享
- 2024-12-22wordpress有哪些好的安全插件?-icode9专业技术文章分享
- 2024-12-22wordpress如何查看系统有哪些cron任务?-icode9专业技术文章分享
- 2024-12-21Svg Sprite Icon教程:轻松入门与应用指南
- 2024-12-20Excel数据导出实战:新手必学的简单教程
- 2024-12-20RBAC的权限实战:新手入门教程
- 2024-12-20Svg Sprite Icon实战:从入门到上手的全面指南
- 2024-12-20LCD1602显示模块详解
- 2024-12-20利用Gemini构建处理各种PDF文档的Document AI管道