0Pricing
Learn Rust Coding · 课时

即时模式 UI 基础

理解 egui 如何进行渲染。

即时模式 UI 基础 是 CoddyKit 上的免费 Learn Rust Coding 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Learn Rust Coding 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Learn Rust Coding 课程共包含 4 节课。

即时模式的含义

egui 是一个即时模式 GUI 库。与 GTK、Qt 这类保留模式工具包不同,后者会构建持久化的控件树,而 egui 会在每一帧从头开始重建整个 UI。

您的代码会在每一帧从上到下运行,并通过函数调用发出控件。这里没有存储的节点图——UI 只是运行闭包所产生的副作用。

更新循环

egui 应用会实现 eframe::App,其 update 方法每帧调用一次,通常每秒调用 60 次。

在 update 中,您要根据当前状态描述 UI 此刻应呈现的样子。egui 不会计算差异,而是直接重新发出全部内容。

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _f: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.label("Hello, egui!");
        });
    }
}

上下文和 Ui

有两种核心类型会在各处出现。egui::Context 是用于访问本帧整个 UI 状态的共享句柄,克隆它的成本很低。

Ui 是用于添加控件的区域。面板和窗口会在闭包中提供一个 &mut Ui;您可以在其上调用 ui.label 或 ui.button 等方法。

egui::CentralPanel::default().show(ctx, |ui| {
    ui.heading("Dashboard");
    ui.separator();
    ui.label("Widgets go here.");
});

控件会返回响应

由于 UI 会在每帧重建,您无法像在保留模式工具包中那样注册回调。相反,每次控件调用都会立即返回一个 Response。

您可以在同一帧检查这个 Response:.clicked()、.hovered()、.changed()。这样,事件处理就能与布局代码保持在一起。

if ui.button("Save").clicked() {
    self.save();
}
let resp = ui.text_edit_singleline(&mut self.name);
if resp.changed() {
    self.dirty = true;
}

状态由您维护

egui 几乎不存储任何应用数据。您的控件值保存在 self 中的 App 结构体里,您会将可变引用传入控件。

文本字段接收 &mut String;复选框接收 &mut bool。egui 会通过引用写回数据,因此您的结构体就是唯一的事实来源。

struct MyApp {
    name: String,
    enabled: bool,
}

// inside update:
ui.text_edit_singleline(&mut self.name);
ui.checkbox(&mut self.enabled, "Enabled");

设置 eframe

eframe 是在桌面和 Web 上承载 egui 的官方框架。它负责原生窗口、GPU 表面和事件循环。

您可以通过 eframe::run_native 启动程序,并传入窗口标题、原生选项以及用于构建您的 App 的闭包。

fn main() -> eframe::Result<()> {
    let opts = eframe::NativeOptions::default();
    eframe::run_native(
        "My App",
        opts,
        Box::new(|_cc| Ok(Box::new(MyApp::default()))),
    )
}

由输入驱动重绘

默认情况下,egui 只会在发生某些事情时重绘:鼠标移动、按键,或显式请求重绘。这样可以节省空闲应用的 CPU 资源。

对于动画或实时数据,请调用 ctx.request_repaint() 来安排下一帧,或者使用带时长参数的 request_repaint_after 进行定时更新。

ui.label(format!("Tick: {}", self.counter));
self.counter += 1;
ctx.request_repaint(); // keep animating

基本无需保留控件 ID

egui 根据调用顺序和位置推导控件身份,并自动生成 Id。对于需要在帧之间保持稳定状态的可折叠标题等控件,这一点很重要。

当两个控件可能发生冲突时——例如循环中标签相同的按钮——请用 ui.push_id(i, |ui| ...) 包裹它们,以消除歧义。

for (i, item) in self.items.iter().enumerate() {
    ui.push_id(i, |ui| {
        if ui.button(&item.label).clicked() {
            println!("clicked {}", i);
        }
    });
}

即时模式的取舍

即时模式让界面代码天然由数据驱动:一个 if 就能显示或隐藏某个区域,一个 for 就能渲染列表。您无需手动添加或移除节点,也不会出现模型与视图不同步的问题。

代价是每一帧都会重新运行整个界面,因此请保持每帧的工作量较小,并避免在 update 中进行繁重计算。

if self.logged_in {
    ui.label(format!("Welcome, {}", self.user));
} else {
    ui.label("Please sign in.");
}

最小完整应用

把这些内容组合起来:结构体保存状态,update 绘制界面,main 运行窗口。这就是任何 egui 桌面程序的完整骨架。

其他所有内容——布局、主题、打包——都建立在这个循环之上。

#[derive(Default)]
struct App { count: i32 }

impl eframe::App for App {
    fn update(&mut self, ctx: &egui::Context, _: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            if ui.button("+1").clicked() { self.count += 1; }
            ui.label(format!("Count: {}", self.count));
        });
    }
}

Rust 为何钟爱 egui

egui 的设计充分发挥了 Rust 的优势。在一次 update 调用中将 &mut self 借用出去,可以让借用检查器保证控件与您的模型之间不会发生数据竞争。

这里没有捕获共享可变状态的回调,也没有因为保留树而被迫使用 Rc<RefCell> 图结构——只有简单的所有权,以及每帧一次可变遍历。

快速检查

测试您对即时模式的理解。

总结

egui 采用即时模式:整个界面都会在每一帧的 eframe::App::update 中重新构建。控件是返回 Response 的函数调用,您可以立即检查其结果。

您的数据保存在 self 中,并通过可变引用传递,因此借用检查器会让模型与视图保持同步。eframe::run_native 负责承载窗口和事件循环。接下来我们将探索控件集合和布局系统。

常见问题解答

「即时模式 UI 基础」课时是免费的吗?

是的 — 「即时模式 UI 基础」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Learn Rust Coding 课程的其余内容,请升级到 CoddyKit PRO。 Learn Rust Coding 课程共包含 4 节课。

「即时模式 UI 基础」这节课中我会学到什么?

理解 egui 如何进行渲染。 你通过在浏览器中直接运行的动手代码来练习 Learn Rust Coding,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Learn Rust Coding 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Learn Rust Coding 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。

「即时模式 UI 基础」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Learn Rust Coding 课中编写并运行代码吗?

能。每节 Learn Rust Coding 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 即时模式 UI 基础
  2. 组件与布局
  3. 管理应用状态
  4. 打包桌面应用
← 返回 Learn Rust Coding