說在前面
- rust新手,egui沒啥找到啥教程,這里自己記錄下學(xué)習(xí)過程
- 環(huán)境:windows11 22H2
- rust版本:rustc 1.71.1
- egui版本:0.22.0
- eframe版本:0.22.0
- 上一篇:這里
serde
-
app.rs
中首先定義了我們的TemplateApp
結(jié)構(gòu)體/// 繼承序列化以及反序列化 用于存儲一些狀態(tài)數(shù)據(jù) #[derive(serde::Deserialize, serde::Serialize)] #[serde(default)] // 在反序列化時(shí),缺少的字段會使用Default特征對應(yīng)的值進(jìn)行初始化 pub struct TemplateApp { // Example stuff: label: String, // 聲明該字段跳過序列化 #[serde(skip)] value: f32, } // 為TemplateApp實(shí)現(xiàn)Default特征 impl Default for TemplateApp { fn default() -> Self { Self { // Example stuff: label: "Hello World!".to_owned(), value: 2.7, } } }
- 在定義
TemplateApp
時(shí),我們讓其繼承了serde::Deserialize, serde::Serialize
。serde
是rust中用于序列化和反序列化(serialize and deserialize)一個(gè)框架。詳細(xì)見這里 - 在
eframe
中,我們使用的是ron
提供的序列化實(shí)現(xiàn),與json
類似,但并不一致,例如以下是一個(gè)ron
序列化的結(jié)果:
詳細(xì)請參考https://github.com/ron-rs/ronScene( // 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", ), ], )
- 看一個(gè)簡單的
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)
- 關(guān)于更深層次的內(nèi)容這里就不再展開了
(咱也展開不下去)。
持久化存儲
- 有了
serde
之后我們可以干什么呢?讓我們繼續(xù)看代碼:impl TemplateApp { /// 在第一幀之前調(diào)用 pub fn new(cc: &eframe::CreationContext<'_>) -> Self { // 我們也可以在這里定義我們的界面樣式 使用`cc.egui_ctx.set_visuals` and `cc.egui_ctx.set_fonts`. // 加載一些應(yīng)用狀態(tài)(比如上一次打開了那些文件之類的) 但是我們必須啟用`persistence`特性 if let Some(storage) = cc.storage { // 這里我們使用ron取出存入的狀態(tài)數(shù)據(jù) 并將其反序列化成TemplateApp return eframe::get_value(storage, eframe::APP_KEY).unwrap_or_default(); } Default::default() } } impl eframe::App for TemplateApp { /// 在應(yīng)用關(guān)閉前調(diào)用 用于存儲狀態(tài) fn save(&mut self, storage: &mut dyn eframe::Storage) { // 這里我們使用ron將TemplateApp序列化 并且存入對應(yīng)的文件中 eframe::set_value(storage, eframe::APP_KEY, self); }
- 首先我們?yōu)?code>TemplateApp實(shí)現(xiàn)了new方法
- 而在之前的
main.rs
中,我們可以看到該方法的調(diào)用,實(shí)際上,該函數(shù)是在eframe
的各種準(zhǔn)備工作完成后,才進(jìn)行的回調(diào)eframe::run_native( "demo app", native_options, Box::new(|cc| Box::new(demo_app::TemplateApp::new(cc))), )
- 在該函數(shù)中,我們完成了一些狀態(tài)數(shù)據(jù)的還原,即讀取應(yīng)用上一次的工作狀態(tài),那么這些數(shù)據(jù)又是在什么時(shí)候存儲下來的呢?以及存在了哪里呢?
- 在接下來的代碼中,我們實(shí)現(xiàn)了
eframe::App
特征,在save
方法中,我們對狀態(tài)數(shù)據(jù)進(jìn)行了存儲,我們可以看看eframe::set_value
的具體實(shí)現(xiàn):#[cfg(feature = "ron")] pub fn set_value<T: serde::Serialize>(storage: &mut dyn Storage, key: &str, value: &T) { // 首先對TemplateApp進(jìn)行序列化 match ron::ser::to_string(value) { // 如果序列化成功 那么進(jìn)一步進(jìn)行存儲 這里并不會立即寫文件 Ok(string) => storage.set_string(key, string), // 失敗則打印日志 Err(err) => log::error!("eframe failed to encode data using ron: {}", err), } }
- 我們可以運(yùn)行一下應(yīng)用看看效果,先修改輸入:
關(guān)閉應(yīng)用后再打開:
可以看到字符串確實(shí)保持一致,而數(shù)值已經(jīng)變回原樣了。 - 那我們的數(shù)據(jù)到底存儲在哪里呢?參照上一節(jié)的做法,將
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"…
- 打開文件,可以看到存儲的內(nèi)容確實(shí)在,其中還存儲了一些其他數(shù)據(jù)
- 當(dāng)我們直接修改對應(yīng)的數(shù)據(jù)后再打開應(yīng)用,對應(yīng)的數(shù)據(jù)也發(fā)生了變化:
- 既然是單個(gè)文件存儲,那么是否會有競爭問題呢?我們打開兩個(gè)應(yīng)用A,B
A想要改字符串,B同時(shí)改了字符串和數(shù)值,B先關(guān)閉,A后關(guān)閉
再次打開應(yīng)用,B修改的數(shù)據(jù)丟失了
因此在開發(fā)/使用的時(shí)候需要注意多窗口下的數(shù)據(jù)存儲問題
參考
- serde
- serde api
- ron
文章來源地址http://www.zghlxwxcb.cn/news/detail-666937.html
文章來源:http://www.zghlxwxcb.cn/news/detail-666937.html
到了這里,關(guān)于【rust/egui】(三)看看template的app.rs:序列化、持久化存儲的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!