Rust GUI库 egui 的简单应用

打印 上一主题 下一主题

主题 838|帖子 838|积分 2514

目录

简介

egui(发音为“e-gooey”)是一个简单、快速且高度可移植的 Rust 即时模式 GUI 库,跨平台、Rust原生,得当一些小工具和游戏引擎GUI:
文档:https://docs.rs/egui/latest/egui/
演示:https://www.egui.rs/#demo
github:https://github.com/emilk/egui
关于即时模式GUI,可以参考 利用C++界面框架ImGUI开发一个简单步伐 里面的介绍,ImGUI是C++的一个即时模式GUI库。

简单示例

创建项目

首先利用cargo工具快速构建项目:
  1. cargo new eguitest
复制代码
然后添加依赖:
  1. cargo add eframe
复制代码
egui只是一个图形库,而不是图形界面开发框架,eframe是与egui配套利用的图形框架
为了静态插入图片,还须要增长egui_extras依赖:
  1. cargo add egui_extras
复制代码
然后在Cargo.toml文件中编辑features
  1. egui_extras = { version = "0.26.2", features = ["all_loaders"] }
复制代码
界面设计

打开src/main.rc,编写第一个eframe示例步伐:
  1. //隐藏Windows上的控制台窗口
  2. #![windows_subsystem = "windows"]
  3. use eframe::egui;
  4. fn main() -> Result<(), eframe::Error> {
  5.     // 创建视口选项,设置视口的内部大小为320x240像素
  6.     let options = eframe::NativeOptions {
  7.         viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
  8.         ..Default::default()
  9.     };
  10.     // 运行egui应用程序
  11.     eframe::run_native(
  12.         "My egui App", // 应用程序的标题
  13.         options, // 视口选项
  14.         Box::new(|cc| {
  15.             // 为我们提供图像支持
  16.             egui_extras::install_image_loaders(&cc.egui_ctx);
  17.             // 创建并返回一个实现了eframe::App trait的对象
  18.             Box::new(MyApp::new(cc))
  19.         }),
  20.     )
  21. }
  22. //定义 MyApp 结构体
  23. struct MyApp {
  24.     name: String,
  25.     age: u32,
  26. }
  27. //MyApp 结构体 new 函数
  28. impl MyApp {
  29.     fn new(cc: &eframe::CreationContext<'_>) -> Self {        
  30.         // 结构体赋初值
  31.         Self {
  32.             name: "Arthur".to_owned(),
  33.             age: 42,
  34.         }
  35.     }
  36. }
  37. //实现 eframe::App trait
  38. impl eframe::App for MyApp {
  39.     fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
  40.         // 在中央面板上显示egui界面
  41.         egui::CentralPanel::default().show(ctx, |ui| {
  42.             // 显示标题
  43.             ui.heading("My egui Application");
  44.             // 创建一个水平布局
  45.             ui.horizontal(|ui| {
  46.                 // 显示姓名标签
  47.                 let name_label = ui.label("Your name: ");
  48.                 // 显示姓名输入框(单行文本框)
  49.                 ui.text_edit_singleline(&mut self.name)
  50.                     .labelled_by(name_label.id); // 关联标签
  51.             });
  52.             // 显示年龄滑块
  53.             ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));
  54.             if ui.button("Increment").clicked() {
  55.                 // 点击按钮后将年龄加1
  56.                 self.age += 1;
  57.             }
  58.             // 显示问候语
  59.             ui.label(format!("Hello '{}', age {}", self.name, self.age));            
  60.             // 显示图片,图片放在main.rs的同级目录下(可以自定义到其它目录)
  61.             ui.image(egui::include_image!("ferris.png"));
  62.         });
  63.     }
  64. }
复制代码
运行结果:

自定义图标

先导入image库,在终端中运行:
  1. impl MyApp {
  2.     // 切换主题
  3.     fn theme_switcher(&mut self, ui: &mut egui::Ui, ctx: &egui::Context) {
  4.         ui.horizontal(|ui| {
  5.             if ui.button("Dark").clicked() {
  6.                 ctx.set_visuals(egui::Visuals::dark());
  7.             }
  8.             if ui.button("Light").clicked() {
  9.                 ctx.set_visuals(egui::Visuals::light());
  10.             }
  11.         });
  12.     }
  13. }
复制代码
还须要导入std::sync::Arc、eframe::egui::IconData ,库引入区如下:
  1. egui::CentralPanel::default().show(ctx, |ui| {
  2.    //...
  3.    // 切换主题
  4.    self.theme_switcher(ui, ctx);
  5.    // 显示图片
  6.    ui.image(egui::include_image!("ferris.png"));
  7. });
复制代码
在main()函数中将native_options的声明改为可变变量的声明,并加入改变图标代码:
  1. //自定义字体
  2. fn setup_custom_fonts(ctx: &egui::Context) {
  3.     // 创建一个默认的字体定义对象
  4.     let mut fonts = egui::FontDefinitions::default();
  5.     //安装的字体支持.ttf和.otf文件
  6.     //文件放在main.rs的同级目录下(可以自定义到其它目录)
  7.     fonts.font_data.insert(
  8.         "my_font".to_owned(),
  9.         egui::FontData::from_static(include_bytes!(
  10.             "msyh.ttc"  
  11.         )),
  12.     );
  13.     // 将字体添加到 Proportional 字体族的第一个位置
  14.     fonts
  15.         .families
  16.         .entry(egui::FontFamily::Proportional)
  17.         .or_default()
  18.         .insert(0, "my_font".to_owned());
  19.     // 将字体添加到 Monospace 字体族的末尾
  20.     fonts
  21.         .families
  22.         .entry(egui::FontFamily::Monospace)
  23.         .or_default()
  24.         .push("my_font".to_owned());
  25.     // 将加载的字体设置到 egui 的上下文中
  26.     ctx.set_fonts(fonts);
  27. }
复制代码
经典结构

在上面示例的基础上,实现一个上中下或左中右的经典三栏结构,main函数不须要修改,只须要修改MyApp结构体的定义即可。
定义导航变量

先定义一个导航枚举,用来在标记当前要体现的界面:
  1. //...
  2. impl MyApp {
  3.     fn new(cc: &eframe::CreationContext<'_>) -> Self {
  4.         //加载自定义字体
  5.         setup_custom_fonts(&cc.egui_ctx);     
  6.         //...
  7.     }
  8. }
  9. //...
复制代码
为了方便理解示例,在 MyApp 中只定义一个 page 字段,并同步修改new函数:
[code]//定义 MyApp 结构体struct MyApp {    pageage,}//MyApp 结构体 new 函数impl MyApp {    fn new(cc: &eframe::CreationContext

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曹旭辉

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表