أساسيات واجهة المستخدم Immediate-Mode
افهم كيفية قيام egui بالتصيير
أساسيات واجهة المستخدم Immediate-Mode درس مجاني في Learn Rust Coding على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Learn Rust Coding، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Learn Rust Coding 4 دروس في المجموع.
بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.
What Immediate Mode Means
egui is an immediate-mode GUI library. Unlike retained-mode toolkits (GTK, Qt) where you build a persistent widget tree, egui rebuilds the entire UI from scratch on every frame.
Your code runs top-to-bottom each frame, emitting widgets as function calls. There is no stored node graph — the UI is just a side effect of running your closure.
The Update Loop
An egui app implements eframe::App, whose update method is called once per frame, typically 60 times a second.
Inside update you describe what the UI should look like right now, given current state. egui diffs nothing — it simply re-emits everything.
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!");
});
}
}Context and Ui
Two core types appear everywhere. egui::Context is the shared, cheaply-cloneable handle to the whole UI state for the frame.
Ui is a region you add widgets into. Panels and windows hand you a &mut Ui inside their closure; you call methods like ui.label or ui.button on it.
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("Dashboard");
ui.separator();
ui.label("Widgets go here.");
});Widgets Return Responses
Because the UI is rebuilt each frame, you cannot register callbacks the way retained toolkits do. Instead, every widget call returns a Response immediately.
You inspect the Response in the same frame: .clicked(), .hovered(), .changed(). This keeps event handling inline with layout.
if ui.button("Save").clicked() {
self.save();
}
let resp = ui.text_edit_singleline(&mut self.name);
if resp.changed() {
self.dirty = true;
}State Lives in You
egui stores almost no application data. Your widget values live in self on the App struct, and you pass mutable references into widgets.
A text field takes &mut String; a checkbox takes &mut bool. egui writes back through the reference, so your struct is the single source of truth.
struct MyApp {
name: String,
enabled: bool,
}
// inside update:
ui.text_edit_singleline(&mut self.name);
ui.checkbox(&mut self.enabled, "Enabled");Setting Up eframe
eframe is the official framework that hosts egui on desktop and web. It owns the native window, the GPU surface, and the event loop.
You launch with eframe::run_native, passing a window title, native options, and a closure that builds your App.
fn main() -> eframe::Result<()> {
let opts = eframe::NativeOptions::default();
eframe::run_native(
"My App",
opts,
Box::new(|_cc| Ok(Box::new(MyApp::default()))),
)
}Repaint Driven by Input
By default egui only repaints when something happens: mouse move, key press, or an explicit request. This saves CPU on idle apps.
For animations or live data, call ctx.request_repaint() to schedule another frame, or request_repaint_after with a duration for timed updates.
ui.label(format!("Tick: {}", self.counter));
self.counter += 1;
ctx.request_repaint(); // keep animatingNo Retained Widget IDs (Mostly)
egui derives widget identity from call order and position, generating an Id automatically. This matters for things like collapsing headers that need stable memory between frames.
When two widgets would collide — e.g. buttons with the same label in a loop — wrap them with ui.push_id(i, |ui| ...) to disambiguate.
for (i, item) in self.items.iter().enumerate() {
ui.push_id(i, |ui| {
if ui.button(&item.label).clicked() {
println!("clicked {}", i);
}
});
}Immediate Mode Trade-offs
Immediate mode makes UI code trivially data-driven: an if shows or hides a section, a for renders a list. There is no manual add/remove of nodes and no desync between model and view.
The cost is that the whole UI re-runs each frame, so keep per-frame work cheap and avoid heavy computation inside update.
if self.logged_in {
ui.label(format!("Welcome, {}", self.user));
} else {
ui.label("Please sign in.");
}Minimal Complete App
Putting it together: a struct holds state, update draws it, and main runs the window. This is the entire skeleton of any egui desktop program.
Everything else — layout, theming, packaging — builds on this loop.
#[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));
});
}
}Why Rust Loves egui
egui's design plays to Rust's strengths. Borrowing &mut self into a single update call means the borrow checker guarantees no data races between widgets and your model.
There are no callbacks capturing shared mutable state, no Rc<RefCell> graphs forced by a retained tree — just plain ownership and one mutable pass per frame.
Quick Check
Test your grasp of immediate mode.
Recap
egui is immediate-mode: the whole UI is rebuilt each frame inside eframe::App::update. Widgets are function calls that return a Response you inspect right away.
Your data lives in self and is passed by mutable reference, so the borrow checker keeps model and view in sync. eframe::run_native hosts the window and event loop. Next we explore the widget palette and layout system.
الأسئلة الشائعة
هل درس «أساسيات واجهة المستخدم Immediate-Mode» مجاني؟
نعم — نص درس «أساسيات واجهة المستخدم Immediate-Mode» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Learn Rust Coding، انتقل إلى CoddyKit PRO. تتضمن دورة Learn Rust Coding 4 دروس في المجموع.
ماذا ستتعلم في «أساسيات واجهة المستخدم Immediate-Mode»؟
افهم كيفية قيام egui بالتصيير تتمرن على Learn Rust Coding مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Learn Rust Coding؟
لا تُشترط خبرة سابقة. Learn Rust Coding على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «أساسيات واجهة المستخدم Immediate-Mode»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Learn Rust Coding هذا؟
نعم. كل درس في Learn Rust Coding يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات واجهة المستخدم Immediate-Mode
- الأدوات والتخطيط
- إدارة حالة التطبيق
- تجهيز تطبيق سطح المكتب