iced
Elm-inspired reactive GUIs in Rust - explicit messages, immutable updates, and native widgets.
Search across all documentation pages
Elm-inspired reactive GUIs in Rust - explicit messages, immutable updates, and native widgets.
use iced::widget::{button, column, text};
use iced::Element;
pub fn update(count: &mut i32, message: Message) {
match message {
Message::Increment => *count += 1,
}
}
pub fn view(count: &i32) -> Element<Message> {
column![
text(format!("{count}")),
button("+").on_press(Message::Increment),
]
.into()
}When to reach for this:
use iced::widget::{button, column, text, Column};
use iced::{application, Element};
#[derive(Debug, Clone)]
enum Message {
Increment,
Decrement,
}
struct Counter {
value: i32,
}
impl Counter {
fn new() -> Self {
Self { value: 0 }
}
fn update(&mut self, message: Message) {
match message {
Message::Increment => self.value += 1,
Message::Decrement => self.value -= 1,
}
}
fn view(&self) -> Element<Message> {
column![
text(format!("{}", self.value)),
button("+").on_press(Message::Increment),
button("-").on_press(Message::Decrement),
]
.into()
}
}
fn main() -> iced::Result {
application("Counter", Counter::update, Counter::view)
.run_with(Counter::new)
}What this demonstrates:
application helper wiring update/viewMessage.update mutates model; view rebuilds Element tree.Subscription streams external events (time, keyboard).| Piece | Role |
|---|---|
| Model | App state struct |
| Message | Event enum |
| update | State transition |
| view | UI function |
view functions - hard to maintain. Fix: split into submodules returning Element.subscription - timers never fire. Fix: wire application::subscription when using async sources.Arc for read-only chunks in model.| Alternative | Use When | Don't Use When |
|---|---|---|
| egui | Immediate-mode tools | Prefer strict MVU testing |
| Tauri | Web UI team | No HTML desired |
| Slint | Designer-driven DSL | Rust-only widget code preferred |
| Qt via CXX | Mature native controls | Pure Rust dependency goal |
Pure update functions unit test without running window - pass messages, assert model.
Use Command/Task patterns (version-dependent) to perform HTTP and map result to Message.
Theme customization and style methods on widgets for brand colors.
Supported in advanced APIs - start single-window until needed.
wgpu for GPU acceleration; software renderer for CI and headless screenshots.
Model routes as enum; view matches route to page functions.
Store field errors in model; display near widgets in view.
Packaging & Distribution for release binaries.
State & Architecture for MVU + layers.
iced retained/diff; egui immediate - see egui.
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 16, 2026