文章目录
下载和演示
egui,我喜欢管它叫恶鬼,是Rust原生的用户图形界面,轻量且快捷,具体风格可见官方的demo,整体来说还挺小清新的。
官方文档给出了边做边学的建议,具体来说,就是克隆其eframe的一个实现,然后以此为模板逐步学习。但我推荐一步到位,直接克隆egui,然后进入其example文件夹,使用cargo命令进行编译
git clone https://github.com/emilk/egui.git
cd egui
cd examples
cargo run --release -p hello_world
运行结果如下

如果出现什么网络问题,可以通过换源来解决,具体方法是添加下面两个环境变量
| 变量名 | 变量值 |
|---|---|
| RUSTUP_DIST_SERVER | https://mirrors.ustc.edu.cn/rust-static |
| RUSTUP_UPDATE_ROOT | https://mirrors.ustc.edu.cn/rust-static/rustup |
配置文件
在生成这个测试项目的过程中,命令行不断地下载各种玩意,当我们看到My egui Application时,egui目录下出现了一个Target文件夹,占据了400多兆的硬盘空间。其中的release文件夹下,有一个【hellow_world.exe】即为最后的可执行文件,只有4M多,控制得还不错。
hello_world是egui中最简单的示例,其文件结构如下,只有一个配置文件和一个main源代码
- src
- Cargo.toml
【Cargo.toml】是配置文件,内容如下,前面诸如名字、版本等信息无关紧要,但后面的依赖项需要注意,给定了eframe的位置。
toml
[package]
name = "hello_world"
version = "0.1.0"
authors = ["Emil Ernerfeldt <emil.ernerfeldt@gmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2024"
rust-version = "1.88"
publish = false
[lints]
workspace = true
[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"] }
源代码粗讲
对于初学者来说,示例程序的代码过于复杂了,所以本文只对其整体结构进行粗略的讲解。
首先,源代码第一行用于隐藏Window命令行,第二行告诉编译器没写文档,不用警告,接下来调用eframe中的egui库。
rust
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#![allow(rustdoc::missing_crate_level_docs)] //没写文档
use eframe::egui;
main函数,内容如下,首先设置一个参数变量,里面包含了窗口的初始尺寸;然后执行run_native,即开启窗口,里面有三个参数,分别是窗口名称、刚刚创建的参数文件,以及最重要的,一个新建的App窗口。
rust
fn main() -> eframe::Result {
env_logger::init();
let options = eframe::NativeOptions {
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);
Ok(Box::<MyApp>::default())
}),
)
}
在main函数中,用到了Box::<MyApp>,其中MyApp是一个自定义的结构体,内容如下,其中主要有两个变量,分别是字符串类型的name和整型的age。
然后为其绑定Default方法,给出了默认姓名和年龄,这两步显然没什么好说的。
rust
struct MyApp {
name: String,
age: u32,
}
impl Default for MyApp {
fn default() -> Self {
Self {
name: "Arthur".to_owned(),
age: 42,
}
}
}
接下来则是关键内容,为MyApp绑定了eframe中的方法。
rust
impl eframe::App for MyApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |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);
});
ui.add(egui::Slider::new(&mut self.age, 0..=120).text("age"));
if ui.button("Increment").clicked() {
self.age += 1;
}
ui.label(format!("Hello '{}', age {}", self.name, self.age));
ui.image(egui::include_image!(
"../../../crates/egui/assets/ferris.png"
));
});
}
}
其中,
- 【ui.heading】是窗口名。
- 【ui.horizontal】是一个水平的布局框,其内部的元素横向布置。在上述代码中,里面摆放了一个写着Your name的label标签,以及一个可编辑的文本框。
- 【egui::Slider::new】添加一个滚动条,滚动条的范围是0到120,滚动条的标记是age。
- 【ui.image】对应Rust的Logo图片。