【rust/egui】(三)看看template的app.rs:序列化、持久化存储

news2024/11/17 5:38:05

说在前面

  • rust新手,egui没啥找到啥教程,这里自己记录下学习过程
  • 环境:windows11 22H2
  • rust版本:rustc 1.71.1
  • egui版本:0.22.0
  • eframe版本:0.22.0
  • 上一篇:这里

serde

  • app.rs中首先定义了我们的TemplateApp结构体
    /// 继承序列化以及反序列化 用于存储一些状态数据
    #[derive(serde::Deserialize, serde::Serialize)]
    #[serde(default)] // 在反序列化时,缺少的字段会使用Default特征对应的值进行初始化
    pub struct TemplateApp {
        // Example stuff:
        label: String,
    
        // 声明该字段跳过序列化
        #[serde(skip)]
        value: f32,
    }
    // 为TemplateApp实现Default特征
    impl Default for TemplateApp {
        fn default() -> Self {
            Self {
                // Example stuff:
                label: "Hello World!".to_owned(),
                value: 2.7,
            }
        }
    }
    
  • 在定义TemplateApp时,我们让其继承了serde::Deserialize, serde::Serializeserde是rust中用于序列化和反序列化(serialize and deserialize)一个框架。详细见这里
  • eframe中,我们使用的是ron提供的序列化实现,与json类似,但并不一致,例如以下是一个ron序列化的结果:
    Scene( // class name is optional
        materials: { // this is a map
            "metal": (
                reflectivity: 1.0,
            ),
            "plastic": (
                reflectivity: 0.5,
            ),
        },
        entities: [ // this is an array
            (
                name: "hero",
                material: "metal",
            ),
            (
                name: "monster",
                material: "plastic",
            ),
        ],
    )
    
    详细请参考https://github.com/ron-rs/ron
  • 看一个简单的ron序列化例子
    use serde::{Deserialize, Serialize};
    
    #[derive(Debug, Deserialize, Serialize)]
    struct MyStruct {
        boolean: bool,
        float: f32,
    }
    
    impl MyStruct {
        fn new() -> Self {
            return ron::from_str("(boolean: true, float: 1.23)").unwrap();
        }
    }
    
    fn main() {
        let x = MyStruct::new();
        println!("RON: {}", ron::to_string(&x).unwrap());
    }
    // output:
    // RON: (boolean:true,float:1.23)
    
  • 关于更深层次的内容这里就不再展开了 (咱也展开不下去)

持久化存储

  • 有了serde之后我们可以干什么呢?让我们继续看代码:
    impl TemplateApp {
        /// 在第一帧之前调用
        pub fn new(cc: &eframe::CreationContext<'_>) -> Self {
            // 我们也可以在这里定义我们的界面样式 使用`cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`.
            
            // 加载一些应用状态(比如上一次打开了那些文件之类的) 但是我们必须启用`persistence`特性
            if let Some(storage) = cc.storage {
            	// 这里我们使用ron取出存入的状态数据 并将其反序列化成TemplateApp
                return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default();
            }
        
            Default::default()
        }
    }
    
    impl eframe::App for TemplateApp {
        /// 在应用关闭前调用 用于存储状态
        fn save(&mut self, storage: &mut dyn eframe::Storage) {
        	// 这里我们使用ron将TemplateApp序列化 并且存入对应的文件中
            eframe::set_value(storage, eframe::APP_KEY, self);
        }
    
  • 首先我们为TemplateApp实现了new方法
  • 而在之前的main.rs中,我们可以看到该方法的调用,实际上,该函数是在eframe的各种准备工作完成后,才进行的回调
    eframe::run_native(
            "demo app",
            native_options,
            Box::new(|cc| Box::new(demo_app::TemplateApp::new(cc))),
        )
    
  • 在该函数中,我们完成了一些状态数据的还原,即读取应用上一次的工作状态,那么这些数据又是在什么时候存储下来的呢?以及存在了哪里呢?
  • 在接下来的代码中,我们实现了eframe::App特征,在save方法中,我们对状态数据进行了存储,我们可以看看eframe::set_value的具体实现:
    #[cfg(feature = "ron")]
    pub fn set_value<T: serde::Serialize>(storage: &mut dyn Storage, key: &str, value: &T) {
    	// 首先对TemplateApp进行序列化
        match ron::ser::to_string(value) {
        	// 如果序列化成功 那么进一步进行存储 这里并不会立即写文件
            Ok(string) => storage.set_string(key, string),
            // 失败则打印日志
            Err(err) => log::error!("eframe failed to encode data using ron: {}", err),
        }
    }
    
  • 我们可以运行一下应用看看效果,先修改输入:
    在这里插入图片描述
    关闭应用后再打开:
    在这里插入图片描述
    可以看到字符串确实保持一致,而数值已经变回原样了。
  • 那我们的数据到底存储在哪里呢?参照上一节的做法,将eframe的日志输出打开,可以看到存储路径打印出来了
    [2023-08-19T09:26:27Z DEBUG eframe] Using the glow renderer
    [2023-08-19T09:26:27Z DEBUG eframe::native::run] Entering the winit event loop (run_return)[2023-08-19T09:26:27Z DEBUG eframe::native::file_storage] Loading app state from "C:\\Users\\xxxx\\AppData\\Roaming\\demo app\\data\\app.ron"
  • 打开文件,可以看到存储的内容确实在,其中还存储了一些其他数据
    在这里插入图片描述
  • 当我们直接修改对应的数据后再打开应用,对应的数据也发生了变化:
    在这里插入图片描述
  • 既然是单个文件存储,那么是否会有竞争问题呢?我们打开两个应用A,B
    在这里插入图片描述
    A想要改字符串,B同时改了字符串和数值,B先关闭,A后关闭
    在这里插入图片描述
    再次打开应用,B修改的数据丢失了
    在这里插入图片描述
    因此在开发/使用的时候需要注意多窗口下的数据存储问题

参考

  • serde
  • serde api
  • ron

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/899580.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023.8.19-2023.8.XX 周报【人脸3D+虚拟服装方向基础调研-Cycle Diffusion\Diffusion-GAN\】更新中

学习目标 1. 这篇是做diffusion和gan结合的&#xff0c;可以参照一下看看能不能做cyclegan的形式&#xff0c;同时也可以调研一下有没有人follow这篇论文做了类似cyclegan的事情 Diffusion-GAN论文精读https://arxiv.org/abs/2206.02262 2. https://arxiv.org/abs/2212.06…

python——json、字典的区别及相互转换方法

前言 json&#xff0c;是一种轻量级的数据交换格式&#xff0c;由JavaScript语言创建&#xff0c;广泛应用于网页数据交互&#xff0c;常见于爬虫和数据分析领域。 json格式简洁、结构清晰&#xff0c;存储格式为&#xff1a;键值对&#xff08;key:value&#xff09; 在pytho…

创作的1024天 分享月入5K的副业心得

机缘 今天早上醒来打开电脑&#xff0c;和往常一样点开csdn&#xff0c;看见有一封私信&#xff0c;原来是系统通知&#xff0c;今天是我成为创作者的1024天&#xff0c;那就趁着这个机会&#xff0c;分享一下目前我月入5K的副业心得。我是一个普通人&#xff0c;最初想成为创…

【100天精通python】Day41:python网络爬虫开发_爬虫基础入门

目录 专栏导读 1网络爬虫概述 1.1 工作原理 1.2 应用场景 1.3 爬虫策略 1.4 爬虫的挑战 2 网络爬虫开发 2.1 通用的网络爬虫基本流程 2.2 网络爬虫的常用技术 2.3 网络爬虫常用的第三方库 3 简单爬虫示例 专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/…

提高 Snowflake 工作效率的 6 大工具

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可二次编辑的3D应用场景 Snowflake 彻底改变了企业存储、处理和分析数据的方式&#xff0c;提供了无与伦比的灵活性、可扩展性和性能。但是&#xff0c;与任何强大的技术一样&#xff0c;要真正利用其潜力&#xff0c;必须拥有…

vsCode使用cuda

一、vsCode使用cuda 前情提要&#xff1a;配置好mingw&#xff1a; 1.安装cuda 参考&#xff1a; **CUDA Toolkit安装教程&#xff08;Windows&#xff09;&#xff1a;**https://blog.csdn.net/qq_42951560/article/details/116131410 2.在vscode中添加includePath c_cp…

VS2015打开Qt的pro项目文件 报错

QT报错&#xff1a;Project ERROR: msvc-version.conf loaded but QMAKE_MSC_VER isn‘t set 解决方法&#xff1a; 找到本机安装的QT路径&#xff0c;找到“msvc-version.conf”文件&#xff0c;用记事本打开&#xff0c; 在其中添加版本“QMAKE_MSC_VER 1900”保存即可。 …

2023-8-18 二进制中1的个数

题目链接&#xff1a;二进制中1的个数 #include <iostream>using namespace std;int lowbit(int x) {return x&-x; }int main() {int n;cin >> n;for(int i 0; i < n; i){int x;cin >> x;int res 0;while(x) x - lowbit(x), res;cout << re…

sql:知识点记录一

1.Mysql逻辑架构&#xff1a;连接层、服务层、引擎层、存储层 2.show engines&#xff1a;查看存储引擎 3.Mysql两种存储引擎的区别&#xff1a; 建立索引&#xff1a;比如说用户很喜欢用name去查询表&#xff0c;就可以给数据库的name字段建立索引&#xff0c;提高查询效率&a…

stm32开关控制led灯泡(附Proteus电路图)

说明&#xff1a;我的灯泡工作电压2V&#xff0c;电流设置为10um,注意了不是10毫安时微安啊&#xff0c;要不然电流太小亮不起来的。 2&#xff1a;我用的开关不是按钮button而是switch, 3&#xff1a;PB0,PB1默认都是低电平&#xff0c;采用了PULLDOWN模式&#xff0c;如果设…

【Alibaba中间件技术系列】「RocketMQ技术专题」让我们一起探索一下DefaultMQPullConsumer的实现原理及源码分析

前提介绍 在RocketMQ中一般有两种获取消息的方式&#xff0c;一个是拉(pull&#xff0c;消费者主动去broker拉取)&#xff0c;一个是推(push&#xff0c;主动推送给消费者)&#xff0c;在上一章节中已经介绍到了相关的Push操作&#xff0c;接下来的章节会介绍Pull操作方式的消…

LRU 算法

LRU 缓存淘汰算法就是一种常用策略。LRU 的全称是 Least Recently Used&#xff0c;也就是说我们认为最近使用过的数据应该是是「有用的」&#xff0c;很久都没用过的数据应该是无用的&#xff0c;内存满了就优先删那些很久没用过的数据。 力扣&#xff08;LeetCode&#xff09…

【最全】Python连接数据库取数与写入数据

不管是做数据分析还是风控建模&#xff0c;都避免不了从数据库中取数&#xff0c;和把数据写入数据库。本文整理连接数据库的不同方法&#xff0c;以及单条写入数据和批量写入数据。所有代码都实测可用&#xff0c;并实际应用于生产&#xff0c;分享给更多在这方面遇到困难的朋…

零基础自学:2023 年的今天,请谨慎进入网络安全行业

前言 2023 年的今天&#xff0c;慎重进入网安行业吧&#xff0c;目前来说信息安全方向的就业对于学历的容忍度比软件开发要大得多&#xff0c;还有很多高中被挖过来的大佬。 理由很简单&#xff0c;目前来说&#xff0c;信息安全的圈子人少&#xff0c;985、211 院校很多都才…

AI 绘画Stable Diffusion 研究(十二)SD数字人制作工具SadTlaker插件安装教程

免责声明: 本案例所用安装包免费提供&#xff0c;无任何盈利目的。 大家好&#xff0c;我是风雨无阻。 想必大家经常看到&#xff0c;无论是在产品营销还是品牌推广时&#xff0c;很多人经常以数字人的方式来为自己创造财富。而市面上的数字人收费都比较昂贵&#xff0c;少则几…

​网安板块是真风口还是炒作?

看需求&#xff0c;官方明确要求政企等在网安上投入的比重不低于10%&#xff0c;而当前&#xff0c;信息安占IT的投入比重不到3%&#xff01;即使是政府对网安和IT合规的要求高&#xff0c;占比高达23.7%&#xff0c;但是全国平均下来也不过5%&#xff0c;距离10%的投入要求&am…

中断之MSI和MSI-X的区别详细总结附图文快速掌握

目录 一、整体介绍二、MSI和MSI-X对比2.1 中断向量连续2.2 映射区域区别2.3 MSI-X配置空间2.3.1 MSI-X Capbility介绍2.3.2 Capbility ID介绍2.3.3 Message Control介绍2.3.4 MSI-X Table介绍2.3.5 MSI-X Pending Table&#xff08;PBA&#xff09;介绍 三、MSI 处理过程3.1 Me…

wsl,字体乱码问题

配置wsl&#xff0c;字体乱码问题 一、前言 用zsh配置好wsl&#xff0c;每次打开还是会出现乱码&#xff0c;只有再新打开一个终端才会显示字体 如下图&#xff1a;第一次打开&#xff0c;出现乱码 如图&#xff1a;按加号&#xff0c;再开一个新终端才会显示字体。 二、解…

IDEA:Error running,Command line is too long. 解决方法

报错如下&#xff1a; Error running SendSmsUtil. Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun.原因是启动命令过长。 解决方法&#xff1a; 1、打开Edit Configurations 2、点击Modify options设置&#x…

React(6)

1.React插槽 import React, { Component } from react import Child from ./compoent/Childexport default class App extends Component {render() {return (<div><Child><div>App下的div</div></Child></div>)} }import React, { Compon…