这是 egui 最简单的入门示例,展示了基本的 UI 控件:Label、TextEdit、Slider、Button 和图片显示。
📁 文件结构
hello_world/
├── Cargo.toml # 项目依赖配置
├── src/
│ └── main.rs # 主程序代码
└── screenshot.png # 运行截图
📦 Cargo.toml 详解
toml
[package]
name = "hello_world" # 项目名称
version = "0.1.0" # 版本号
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"] # 作者(egui 作者)
license = "MIT OR Apache-2.0" # 双许可证
edition = "2024" # Rust 2024 版次
rust-version = "1.92" # 最低 Rust 版本要求
publish = false # 不发布到 crates.io
[lints]
workspace = true # 继承工作区的 lint 配置
[dependencies]
# eframe 主依赖,使用工作区配置,启用 __screenshot 功能用于截图
eframe = { workspace = true, features = [
"default",
"__screenshot", # 可通过 EFRAME_SCREENSHOT_TO 环境变量输出截图
] }
# 图片支持扩展库
egui_extras = { workspace = true, features = ["default", "image"] }
# 日志库,支持彩色输出和时间戳
env_logger = { workspace = true, features = ["auto-color", "humantime"] }
关键点解析
| 依赖 | 作用 |
|---|---|
eframe |
应用框架,提供窗口、事件循环和渲染 |
eframe/__screenshot |
特殊功能,运行时设置 EFRAME_SCREENSHOT_TO=path.png 可保存截图 |
egui_extras |
扩展功能,这里启用 image 功能加载图片 |
env_logger |
日志输出,通过 RUST_LOG=debug 控制日志级别 |
🚀 main.rs 逐行解析
1. 文件头属性
rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#![expect(rustdoc::missing_crate_level_docs)]
| 属性 | 说明 |
|---|---|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] |
发布模式(--release)下在 Windows 隐藏控制台窗口,只显示 GUI 窗口 |
#![expect(rustdoc::missing_crate_level_docs)] |
允许缺少 crate 级别文档(因为是示例) |
2. 引入依赖
rust
use eframe::egui; // 通过 eframe 重新导出使用 egui
3. main 函数
rust
fn main() -> eframe::Result {
// 初始化日志系统,可以通过 RUST_LOG=debug 查看详细日志
env_logger::init();
// 配置窗口选项
let options = eframe::NativeOptions {
// viewport 字段:设置窗口大小 320x240
viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
..Default::default() // 其余使用默认值
};
// 运行应用
eframe::run_native(
"My egui App", // 窗口标题
options, // 窗口配置
Box::new(|cc| { // 应用创建闭包
// 安装图片加载器,支持显示图片
egui_extras::install_image_loaders(&cc.egui_ctx);
// 返回默认的 MyApp 实例
Ok(Box::<MyApp>::default())
}),
)
}
4. 应用状态结构体
rust
struct MyApp {
name: String, // 姓名
age: u32, // 年龄
}
impl Default for MyApp {
fn default() -> Self {
Self {
name: "Arthur".to_owned(), // 默认姓名
age: 42, // 默认年龄
}
}
}
5. 实现 eframe::App trait
rust
impl eframe::App for MyApp {
// ui 方法:每帧调用,绘制界面
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
// 创建一个中央面板(带背景和边距)
egui::CentralPanel::default().show_inside(ui, |ui| {
// 大标题
ui.heading("My egui Application");
// 水平布局:标签 + 文本框
ui.horizontal(|ui| {
let name_label = ui.label("Your name: ");
ui.text_edit_singleline(&mut self.name)
.labelled_by(name_label.id); // 关联标签,辅助功能
});
// 滑块控件,绑定 age,范围 0-120
ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));
// 按钮,点击时 age+1
if ui.button("Increment").clicked() {
self.age += 1;
}
// 显示当前值
ui.label(format!("Hello '{}', age {}", self.name, self.age));
// 显示图片(使用 include_image! 宏在编译时嵌入图片)
ui.image(egui::include_image!(
"../../../crates/egui/assets/ferris.png" // 路径相对于 hello_world 示例
));
});
}
}
🎨 界面控件详解
1. Label(标签)
rust
ui.label("Your name: ");
ui.heading("My egui Application"); // 大标题样式
2. TextEdit(文本编辑框)
rust
ui.text_edit_singleline(&mut self.name) // 绑定到 String
.labelled_by(name_label.id); // 关联标签 ID
3. Slider(滑块)
rust
egui::Slider::new(&mut self.age, 0..=120) // 绑定到 u32,范围 0-120
.text("age") // 显示文本
4. Button(按钮)
rust
if ui.button("Increment").clicked() { // 点击检测
self.age += 1;
}
5. Image(图片)
rust
ui.image(egui::include_image!("path/to/image.png"));
// include_image! 宏在编译时嵌入图片,无需运行时加载
🧠 关键概念理解
即时模式(Immediate Mode)
- 每帧都重新构建 UI
- 状态保存在
MyApp结构体中 - 控件通过返回值(如
.clicked())响应用户操作
布局系统
CentralPanel:占据剩余空间,提供默认背景horizontal:水平排列子控件- 嵌套布局:
CentralPanel包含horizontal
数据绑定
- 控件直接修改应用状态:
&mut self.name、&mut self.age - 无需手动更新 UI,框架自动重绘
图片处理
egui_extras::install_image_loaders初始化图片支持include_image!宏在编译时嵌入图片,适合小图片- 图片路径相对于当前文件
🏃 运行方式
bash
# 普通运行
cargo run -p hello_world
# 带日志调试运行
RUST_LOG=debug cargo run -p hello_world
# 生成截图(需要 __screenshot 功能)
EFRAME_SCREENSHOT_TO=screenshot.png cargo run -p hello_world
📸 运行效果
界面包含:
- 标题 "My egui Application"
- "Your name:" 标签 + 文本输入框(默认 "Arthur")
- 年龄滑块(0-120,默认 42)
- "Increment" 按钮,点击年龄+1
- 显示 "Hello '姓名', 年龄"
- Ferris 螃蟹图片
💡 一句话总结
hello_world 示例展示了 egui 最核心的编程模式:状态存在结构体里,ui 方法每帧重新构建界面,控件直接读写状态,布局通过嵌套 Panel 和 horizontal 实现。