尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

egui Hello World 示例全解析:从 `Label`、`TextEdit`、`Slider` 到 `Button` 的即时模式 GUI 入门

egui Hello World 示例全解析:从 `Label`、`TextEdit`、`Slider` 到 `Button` 的即时模式 GUI 入门 egui Hello World 示例全解析从Label、TextEdit、Slider到Button的即时模式 GUI 入门【免费下载链接】eguiegui: an easy-to-use immediate mode GUI in Rust that runs on both web and native项目地址: https://gitcode.com/GitHub_Trending/eg/egui本文以 egui 仓库中的 hello_world 示例 为主线逐行剖析一个最小可运行的 eframe 桌面应用从cargo run -p hello_world的启动方式到Label、TextEdit、Slider、Button四大基础控件的用法再到include_image!宏与图片加载器的接入原理。读完本文你将掌握如何用 egui 在几分钟内搭起第一个带输入框、滑条、按钮和图片的 Rust 原生窗口应用并理解其背后的核心 API 调用链。一、示例概览与快速运行hello_world 是 egui 仓库中最基础的示例其 README 只有一句话的定位展示Label、TextEdit、Slider、Button等基础 UI 控件。该示例属于仓库根目录 Cargo.toml 中examples/*工作区成员因此可以站在仓库根目录直接用包名运行cargo run -p hello_world运行后会出现一个 320×240 的窗口标题为 “My egui App”界面包含标题文本 “My egui Application”一个 Your name: 标签与单行文本输入框默认内容为Arthur一个带 age 文字的滑条范围 0..120默认值 42一个 Increment 按钮点击后年龄 1一行根据输入实时拼接的问候语Hello xxx, age xxx窗口底部一张内嵌的 egui 吉祥物 ferris 图片。整个示例的完整源码位于 examples/hello_world/src/main.rs全部代码约 60 行非常适合作为新手的第一个 egui 程序。二、程序入口与原生窗口配置2.1 隐藏 Windows 控制台窗口#![cfg_attr(not(debug_assertions), windows_subsystem windows)] // hide console window on Windows in release这一行是 Windows 平台惯例在 release 构建cfg_attr中的not(debug_assertions)下将子系统指定为windows从而隐藏弹出的黑色控制台窗口。调试构建不受影响控制台仍会保留以便观察日志。2.2 日志初始化env_logger::init(); // Log to stderr (if you run with RUST_LOGdebug).env_logger是 egui 生态惯用的日志后端。示例中通过RUST_LOG环境变量控制输出级别例如RUST_LOGdebug cargo run -p hello_world即可在 stderr 看到 eframe、egui 运行时的调试日志。该依赖在 examples/hello_world/Cargo.toml 中声明并启用了auto-color终端着色与humantime人类可读时间戳两个特性。2.3 ViewportBuilder 与 NativeOptionslet options eframe::NativeOptions { viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]), ..Default::default() };egui::ViewportBuilder负责描述窗口/视口viewport的初始属性with_inner_size设定客户区尺寸为 320×240 逻辑像素。除尺寸外它还可以配置窗口标题、位置、是否可缩放、图标等NativeOptions是 eframe 原生后端基于 winit的全局选项集合除viewport外还包含renderer渲染后端选择、persist_window是否记住窗口位置等字段。示例只覆盖viewport其余用..Default::default()取默认值。三、eframe::run_native与Apptrait应用骨架3.1 启动函数eframe::run_native( My egui App, options, Box::new(|cc| { // This gives us image support: egui_extras::install_image_loaders(cc.egui_ctx); Ok(Box::MyApp::default()) }), )eframe::run_native是原生桌面平台的应用入口声明于 crates/eframe/src/lib.rs其三个参数依次为参数类型作用app_namestr应用名称会作为窗口标题与持久化 ID 的一部分native_optionsNativeOptions上述原生窗口/渲染配置app_creator闭包创建App实例的工厂可拿到CreationContext闭包接收cc: eframe::CreationContext其中cc.egui_ctx是全局的egui::Contextinstall_image_loaders正是注册到它上面。注意返回值是eframe::Result因此main的签名是fn main() - eframe::Result。从仓库的调用链看run_native会继续进入run_native_extcrates/eframe/src/lib.rs最终由各原生后端如glow_integration.rs、wgpu_integration.rs驱动事件循环与渲染。3.2 应用状态结构体struct MyApp { name: String, age: u32, } impl Default for MyApp { fn default() - Self { Self { name: Arthur.to_owned(), age: 42, } } }即时模式immediate modeGUI 的核心理念UI 状态就存放在你的普通 Rust 结构体中没有独立的控件对象树。MyApp的两个字段分别被TextEdit和Slider以mut方式直接绑定这正是Box::MyApp::default()能直接作为应用实例的原因——Default提供了初始状态。3.3 实现eframe::Appimpl eframe::App for MyApp { fn ui(mut self, ui: mut egui::Ui, _frame: mut eframe::Frame) { egui::CentralPanel::default().show(ui, |ui| { // ... }); } }注意本仓库当前版本workspace 版本号见 Cargo.toml为 0.36.2的Apptrait 把绘制入口统一收口为fn ui(mut self, ui: mut egui::Ui, frame: mut eframe::Frame)而不是更早版本中常见的fn update(mut self, ctx: egui::Context, frame: mut eframe::Frame)这是新版本 API 的显著变化。CentralPanel会占据窗口中央的剩余区域是所有非面板 UI 的默认容器ui参数则代表当前正在绘制的面板画布示例中所有控件都挂在它下面。四、四大基础控件逐一拆解4.1Label静态文本与无障碍绑定ui.heading(My egui Application);ui.heading是Label的便捷封装按TextStyle::Heading样式绘制大标题。随后let name_label ui.label(Your name: ); ui.text_edit_singleline(mut self.name) .labelled_by(name_label.id);第一行ui.label创建普通Label并捕获其返回的Response中的id第二行通过.labelled_by(...)把输入框与该标签关联。这一做法服务于无障碍AccessKit场景屏幕阅读器可以把标签文本与输入框语义绑定供依赖辅助技术的用户使用。egui 的Response是所有控件交互结果的统一载体是否被点击、悬停、拖拽等也是这类链式配置的入口。4.2TextEdit单行文本输入ui.text_edit_singleline(mut self.name)text_edit_singleline是TextEdit的单行便捷构造直接借用mut String用户每次按键都会写回self.name无需任何手动同步——这是即时模式最直观的体现。对应还有ui.text_edit_multiline多行版本。TextEdit位于 crates/egui/src/widgets/text_edit/ 目录内部还实现了光标状态、IME 输入法合成等细节这里按下不表。4.3Slider数值拖拽与钳制ui.add(egui::Slider::new(mut self.age, 0..120).text(age));Slider::new的第一个参数是被控数值的可变引用支持整数、浮点等数值类型第二个参数是闭区间RangeInclusive定义滑条两端对应的取值边界。.text(age)会在滑条右侧追加说明文字。其底层实现见 crates/egui/src/widgets/slider.rs滑条由“滑轨 数值显示 可选文本”三部分构成数值显示部分可点击后直接键入默认SliderClamping::Always会把值钳制在区间内也可通过.clamping(SliderClamping::Edits)等策略调整见 slider.rs。示例用0..120限定了年龄范围恰好与u32语义吻合。4.4Button点击事件if ui.button(Increment).clicked() { self.age 1; }ui.button创建文本按钮并立即返回Response.clicked()返回“本帧内是否发生点击”。由于即时模式每帧都会重建 UI这里if clicked()的写法等价于传统事件循环中的回调但更直白。按钮的完整能力不止于此——crates/egui/src/widgets/button.rs 显示Button还支持.selected()可选中态自动添加CLASS_SELECTED、.fill()自定义填充色、.min_size()以及Button::image/Button::image_and_text带图标按钮等。点击后self.age 1下一帧滑条与问候语会自动反映新值。4.5 实时反馈输出ui.label(format!(Hello {}, age {}, self.name, self.age));Label接收任意WidgetText可转换类型format!生成的字符串在这里每帧重新求值因此输入框内容、年龄变化都会即时反映到这一行文字上——无需任何数据绑定框架。五、图片加载install_image_loaders与include_image!示例在创建应用时调用了egui_extras::install_image_loaders(cc.egui_ctx)。该函数定义于 crates/egui_extras/src/loaders.rs按编译特性注册一系列加载器到egui::Contextegui_extras 特性注册的加载器支持的来源file非 WasmFileLoaderfile://URI经std::fs::read读取扩展名推断类型httpEhttpLoaderhttp(s)://URI按Content-Type推断类型imageImageCrateLoaderpng/jpeg 等基于imagecratesvgSvgLoader.svg文件示例的 Cargo.toml 中egui_extras启用了default与image两个特性因此本示例可解码 png 等位图。函数内部会先检查ctx.is_loader_installed(...)避免重复安装多次调用是安全的。绘制部分ui.image(egui::include_image!( ../../../crates/egui/assets/ferris.png ));include_image!是 egui 提供的编译期图片内嵌宏定义于 crates/egui/src/lib.rs。它展开为ImageSource::BytesURI 固定为bytes://前缀拼接原始路径字节数据通过include_bytes!在编译期打包进二进制从而运行时零文件读取特别适合图标、吉祥物等小体积资源。ui.image(...)则完成解码、上传 GPU 纹理并绘制示例中的图片是仓库自带的 crates/egui/assets/ferris.png。注意install_image_loaders只负责“字节 → 图像”的解码管线include_image!负责“文件 → 字节”的编译期内嵌二者一前一后配合前者提供解码能力后者提供内嵌字节。六、依赖配置说明示例的 Cargo.toml 依赖结构如下[dependencies] eframe { workspace true, features [ default, __screenshot, # __screenshot is so we can dump a screenshot using EFRAME_SCREENSHOT_TO ] } # For image support: egui_extras { workspace true, features [default, image] } env_logger { workspace true, features [auto-color, humantime] }三个要点eframe是桌面端最上层的开箱即用框架自带 winit 事件循环与渲染器版本与 workspace 统一当前 0.36.2。__screenshot是一个内部特性设置环境变量EFRAME_SCREENSHOT_TO指向输出路径后可自动导出首帧截屏仓库的截图回归测试与示例截图正是靠它生成的。egui_extras仅在示例中用于install_image_loaders所以只额外开启了image特性见 loaders.rs 中关于特性与格式的警告加载器和图像格式必须同时配置才会生效。包本身publish false是仓库内部示例不会发布到 crates.ioedition 为 2024rust-version要求 1.95。七、扩展方向从示例走向真实应用hello_world 演示的只是最小闭环想继续深入可以沿着以下路径在仓库中找到更丰富的参照更多控件仓库的 egui_demo_lib 中收录了数十个控件演示滑条、拖拽值、颜色选择器、表格等cargo run -p egui_demo_app可运行完整的 demo 应用逐个体验布局除了CentralPanelegui 还提供TopBottomPanel、SidePanel等面板与ui.horizontal、ui.vertical布局函数示例中ui.horizontal已用于把标签和输入框排成一行Web 端eframe 同时支持编译到 Wasm 在浏览器运行可参考 crates/eframe/src/web/ 下的 web 后端截图自动化如需为 UI 生成回归快照可参考 egui_kittest 的 snapshot 测试 以及 scripts/accept_snapshots.sh 工具链。总而言之hello_world 用最少的代码串起了“状态结构体 →App::ui→ 各控件读写状态”的完整循环是理解 egui 即时模式心智模型的最佳起点你写 UI 就是写普通 Rust 函数状态变化由控件直接写回你的变量渲染与事件由框架每帧自动完成。【免费下载链接】eguiegui: an easy-to-use immediate mode GUI in Rust that runs on both web and native项目地址: https://gitcode.com/GitHub_Trending/eg/egui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表