Iced is a cross-platform GUI library for Rust, designed with simplicity, type-safety, and performance in mind. It draws significant inspiration from The Elm Architecture, providing a reactive programming model that makes UI development predictable and easy to reason about.
Key Features and Concepts:
1. Elm Architecture Inspired: Iced follows the Model-View-Update (MVU) pattern. Your application's state (`Model`) is updated by messages (`Message`) triggered by user interactions or other events, and then rendered into the UI (`View`).
2. Reactive Programming: The UI automatically reacts to changes in your application's state, simplifying state management and reducing boilerplate.
3. GPU-Accelerated Rendering: Iced leverages `wgpu`, a cross-platform GPU API (based on WebGPU), for rendering. This allows it to create hardware-accelerated user interfaces, resulting in smooth animations and high performance.
4. Cross-Platform: It supports various platforms including Windows, macOS, Linux, and even the Web (via WebAssembly).
5. Widgets: Iced provides a set of built-in widgets (buttons, text, sliders, checkboxes, etc.) and offers the flexibility to create custom widgets, allowing for highly personalized UIs.
6. Asynchronous Runtime: It includes a built-in asynchronous runtime, enabling non-blocking operations and easy integration with asynchronous tasks like network requests.
7. Type Safety: Being built in Rust, Iced benefits from Rust's strong type system, which helps catch many potential UI bugs at compile time.
Core Components:
* `Application` Trait: The heart of an Iced application. You implement this trait for your application's main struct. It defines methods like `new` (initialization), `update` (state modification based on messages), `view` (UI rendering), `subscription` (handling external events), and `title` (window title).
* `Message` Enum: A crucial part of the MVU pattern. `Message`s are typically enums that represent all possible user interactions or events that can change your application's state (e.g., `ButtonPress`, `TextInputChange`).
* `State` Struct: This struct holds the current data or 'model' of your application. It's updated by `Message`s.
* `Command`: Represents an action to be performed, often asynchronously, after an `update`. This can include fetching data from an API, writing to a file, or modifying system state outside the UI logic.
* `Element`: The fundamental building block of the UI. Widgets like `Button`, `Text`, `Column`, `Row` all produce an `Element` which describes a part of the user interface.
Example Code
```rust
use iced::{
button, executor, Align, Application, Button, Command, Element, Length, Row, Settings, Text,
};
pub fn main() -> iced::Result {
Counter::run(Settings::default())
}
// The application's state
struct Counter {
value: i32,
increment_button_state: button::State,
decrement_button_state: button::State,
}
// All possible messages the application can receive
#[derive(Debug, Clone, Copy)]
enum Message {
IncrementPressed,
DecrementPressed,
}
impl Application for Counter {
// The type of executor your application will use.
// `Default` uses `async-std` by default.
type Executor = executor::Default;
// The type of messages your application will produce.
type Message = Message;
// The type of flags, if any, you can pass at initialization.
type Flags = ();
// The type of renderer your application will use.
type Renderer = iced::Renderer;
// Initializes the application state and returns any initial commands.
fn new(_flags: ()) -> (Counter, Command<Message>) {
(
Counter {
value: 0,
increment_button_state: button::State::new(),
decrement_button_state: button::State::new(),
},
Command::none(),
)
}
// Returns the current title of the application window.
fn title(&self) -> String {
String::from("Iced Counter App")
}
// Updates the application state based on the received message.
// Can return `Command`s to perform side effects.
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::IncrementPressed => {
self.value += 1;
}
Message::DecrementPressed => {
self.value -= 1;
}
}
Command::none() // No commands to perform after updating state
}
// Renders the application's user interface.
fn view(&mut self) -> Element<Message> {
Row::new()
.width(Length::Fill)
.align_items(Align::Center)
.spacing(20) // Spacing between elements
.push(
Button::new(&mut self.decrement_button_state, Text::new("-"))
.on_press(Message::DecrementPressed), // Attach message to button press
)
.push(Text::new(self.value.to_string()).size(50)) // Display the counter value
.push(
Button::new(&mut self.increment_button_state, Text::new("+"))
.on_press(Message::IncrementPressed), // Attach message to button press
)
.into() // Convert the Row into an Element
}
}
```
To run this example, add `iced = "0.4"` (or the latest version) to your `Cargo.toml` file under `[dependencies]`. Then, execute `cargo run` in your terminal.








Iced (GUI Library)