Podstawy UI w trybie immediate mode
Zrozumie Pan/Pani, jak egui renderuje interfejs.
Podstawy UI w trybie immediate mode to bezpłatna lekcja Learn Rust Coding na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Learn Rust Coding, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.
Znaczenie trybu natychmiastowego
egui to biblioteka GUI działająca w trybie natychmiastowym. W przeciwieństwie do narzędzi działających w trybie zachowywanym (GTK, Qt), w których tworzysz trwałe drzewo widżetów, egui odtwarza cały interfejs od podstaw w każdej klatce.
W każdej klatce kod jest wykonywany od góry do dołu, a widżety są emitowane jako wywołania funkcji. Nie istnieje przechowywany graf węzłów — interfejs jest jedynie efektem ubocznym wykonania closure.
Pętla aktualizacji
Aplikacja egui implementuje eframe::App, którego metoda update jest wywoływana raz na klatkę, zwykle 60 razy na sekundę.
Wewnątrz update opisujesz, jak interfejs powinien wyglądać w tej chwili, na podstawie bieżącego stanu. egui niczego nie porównuje — po prostu ponownie emituje wszystkie elementy.
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 i Ui
Wszędzie pojawiają się dwa podstawowe typy. egui::Context to współdzielony, tani do klonowania uchwyt do całego stanu interfejsu w danej klatce.
Ui to obszar, do którego dodajesz widżety. Panele i okna przekazują do closure obiekt &mut Ui; wywołujesz na nim metody takie jak ui.label lub ui.button.
egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("Dashboard");
ui.separator();
ui.label("Widgets go here.");
});Widżety zwracają odpowiedzi
Ponieważ interfejs jest odtwarzany w każdej klatce, nie można rejestrować wywołań zwrotnych tak jak w narzędziach działających w trybie zachowywanym. Zamiast tego każde wywołanie widżetu natychmiast zwraca obiekt Response.
Sprawdzasz obiekt Response w tej samej klatce: .clicked(), .hovered(), .changed(). Dzięki temu obsługa zdarzeń pozostaje częścią układu interfejsu.
if ui.button("Save").clicked() {
self.save();
}
let resp = ui.text_edit_singleline(&mut self.name);
if resp.changed() {
self.dirty = true;
}Stan jest przechowywany w aplikacji
egui przechowuje niemal żadnych danych aplikacji. Wartości widgetów znajdują się w self w strukturze App, a do widgetów przekazuje się mutowalne referencje.
Pole tekstowe przyjmuje &mut String, a pole wyboru — &mut bool. egui zapisuje zmiany przez referencję, dzięki czemu struktura jest jedynym źródłem prawdy.
struct MyApp {
name: String,
enabled: bool,
}
// inside update:
ui.text_edit_singleline(&mut self.name);
ui.checkbox(&mut self.enabled, "Enabled");Konfiguracja eframe
eframe to oficjalny framework, który udostępnia egui na komputerach stacjonarnych i w przeglądarce. Zarządza natywnym oknem, powierzchnią GPU oraz pętlą zdarzeń.
Aplikację uruchamia się za pomocą eframe::run_native, przekazując tytuł okna, opcje natywne oraz domknięcie tworzące obiekt App.
fn main() -> eframe::Result<()> {
let opts = eframe::NativeOptions::default();
eframe::run_native(
"My App",
opts,
Box::new(|_cc| Ok(Box::new(MyApp::default()))),
)
}Odświeżanie wywoływane przez dane wejściowe
Domyślnie egui odświeża interfejs tylko wtedy, gdy coś się wydarzy: nastąpi ruch myszy, naciśnięcie klawisza lub jawne żądanie odświeżenia. Dzięki temu aplikacje bezczynne zużywają mniej procesora.
W przypadku animacji lub danych na żywo wywołaj ctx.request_repaint(), aby zaplanować kolejną klatkę, albo użyj request_repaint_after z określonym czasem trwania, aby wykonywać aktualizacje w określonych odstępach.
ui.label(format!("Tick: {}", self.counter));
self.counter += 1;
ctx.request_repaint(); // keep animatingPrzeważnie bez trwałych identyfikatorów widgetów
egui wyprowadza tożsamość widgetu z kolejności wywołań i jego położenia, automatycznie generując Id. Ma to znaczenie w przypadku elementów takich jak zwijane nagłówki, które wymagają zachowania pamięci między klatkami.
Gdy dwa widgety mogłyby mieć ten sam identyfikator — na przykład przyciski z taką samą etykietą w pętli — opakuj je w ui.push_id(i, |ui| ...), aby je rozróżnić.
for (i, item) in self.items.iter().enumerate() {
ui.push_id(i, |ui| {
if ui.button(&item.label).clicked() {
println!("clicked {}", i);
}
});
}Kompromisy trybu natychmiastowego
Tryb natychmiastowy sprawia, że kod interfejsu jest wprost sterowany danymi: instrukcja if pokazuje lub ukrywa sekcję, a pętla for renderuje listę. Nie trzeba ręcznie dodawać ani usuwać węzłów, a model i widok nie mogą się rozsynchronizować.
Ceną jest ponowne wykonywanie całego interfejsu w każdej klatce, dlatego praca wykonywana w każdej klatce powinna być lekka i nie należy umieszczać kosztownych obliczeń wewnątrz update.
if self.logged_in {
ui.label(format!("Welcome, {}", self.user));
} else {
ui.label("Please sign in.");
}Minimalna kompletna aplikacja
Łącząc wszystko: struktura przechowuje stan, update go rysuje, a main uruchamia okno. To cały szkielet dowolnego desktopowego programu egui.
Cała reszta — układ, motywy i pakowanie — opiera się na tej pętli.
#[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));
});
}
}Dlaczego Rust świetnie współpracuje z egui
Projekt egui wykorzystuje mocne strony Rusta. Pożyczenie &mut self w ramach pojedynczego wywołania update sprawia, że borrow checker gwarantuje brak wyścigów danych między widgetami a modelem.
Nie ma tu callbacków przechwytujących współdzielony mutowalny stan ani grafów Rc<RefCell> wymuszanych przez trwałe drzewo — jest zwykła własność i jedno mutowalne przejście w każdej klatce.
Szybki test
Sprawdź, czy rozumie Pan/Pani tryb natychmiastowy.
Podsumowanie
egui działa w trybie natychmiastowym: cały interfejs jest tworzony od nowa w każdej klatce wewnątrz eframe::App::update. Widgety są wywołaniami funkcji zwracającymi obiekt Response, który można od razu sprawdzić.
Dane znajdują się w self i są przekazywane przez mutowalną referencję, dzięki czemu borrow checker utrzymuje synchronizację modelu i widoku. eframe::run_native obsługuje okno i pętlę zdarzeń. Następnie przyjrzymy się zestawowi widgetów i systemowi układu.
Często zadawane pytania
Czy lekcja „Podstawy UI w trybie immediate mode” jest bezpłatna?
Tak — pełny tekst „Podstawy UI w trybie immediate mode” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Learn Rust Coding, przejdź na CoddyKit PRO. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.
Co nauczysz się w „Podstawy UI w trybie immediate mode”?
Zrozumie Pan/Pani, jak egui renderuje interfejs. Ćwiczysz Learn Rust Coding z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Learn Rust Coding?
Nie wymagamy żadnego doświadczenia. Learn Rust Coding w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Podstawy UI w trybie immediate mode”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Learn Rust Coding?
Tak. Każda lekcja Learn Rust Coding zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Podstawy UI w trybie immediate mode
- Widgety i układ
- Zarządzanie stanem aplikacji
- Pakowanie aplikacji desktopowej