Rust UI工具库iced_widget的使用:轻量级跨平台GUI组件库,构建现代化用户界面
Rust UI工具库iced_widget的使用:轻量级跨平台GUI组件库,构建现代化用户界面
安装
在项目目录中运行以下Cargo命令:
cargo add iced_widget
或者在Cargo.toml中添加以下行:
iced_widget = "0.13.4"
基本使用示例
下面是一个使用iced_widget创建简单计数器的完整示例:
use iced::widget::{button, column, text};
use iced::{Alignment, Element, Sandbox, Settings};
// 定义应用状态
struct Counter {
value: i32,
}
// 定义消息类型
#[derive(Debug, Clone)]
enum Message {
Increment,
Decrement,
}
// 实现Sandbox trait
impl Sandbox for Counter {
type Message = Message;
fn new() -> Self {
Self { value: 0 }
}
fn title(&self) -> String {
String::from("Counter - Iced")
}
fn update(&mut self, message: Message) {
match message {
Message::Increment => self.value += 1,
Message::Decrement => self.value -= 1,
}
}
fn view(&self) -> Element<Message> {
// 使用iced_widget提供的组件构建UI
column![
// 显示当前计数值
text(self.value).size(50),
// 增加按钮
button("+").on_press(Message::Increment),
// 减少按钮
button("-").on_press(Message::Decrement),
]
.padding(20)
.align_items(Alignment::Center)
.into()
}
}
fn main() -> iced::Result {
Counter::run(Settings::default())
}
更多UI组件示例
use iced::widget::{button, checkbox, column, container, progress_bar, radio, row, scrollable, slider, text, text_input};
use iced::{Alignment, Color, Element, Length, Sandbox, Settings};
#[derive(Debug, Clone)]
enum Message {
TextInputChanged(String),
CheckboxToggled(bool),
RadioSelected(u8),
SliderChanged(f32),
ButtonPressed,
}
struct WidgetGallery {
text_input_value: String,
checkbox_value: bool,
radio_value: u8,
slider_value: f32,
}
impl Sandbox for WidgetGallery {
type Message = Message;
fn new() -> Self {
Self {
text_input_value: String::new(),
checkbox_value: false,
radio_value极简风格,适合现代UI设计
## 完整示例代码
下面是一个结合了多种iced_widget组件的完整示例,展示了一个简单的待办事项应用:
```rust
use iced::widget::{
button, checkbox, column, container, row, scrollable, text, text_input,
};
use iced::{Alignment, Element, Length, Sandbox, Settings};
// 定义待办事项结构
#[derive(Debug, Clone)]
struct TodoItem {
description: String,
completed: bool,
}
// 定义应用状态
struct TodoApp {
todos: Vec<TodoItem>,
new_todo: String,
}
// 定义消息类型
#[derive(Debug, Clone)]
enum Message {
NewTodoChanged(String),
AddTodo,
ToggleTodo(usize),
}
// 实现Sandbox trait
impl Sandbox for TodoApp {
type Message = Message;
fn new() -> Self {
Self {
todos: Vec::new(),
new_todo: String::new(),
}
}
fn title(&self) -> String {
String::from("Todo App with Iced")
}
fn update(&mut self, message: Message) {
match message {
Message::NewTodoChanged(text) => {
self.new_todo = text;
}
Message::AddTodo => {
if !self.new_todo.is_empty() {
self.todos.push(TodoItem {
description: self.new_todo.clone(),
completed: false,
});
self.new_todo.clear();
}
}
Message::ToggleTodo(index) => {
if let Some(todo) = self.todos.get_mut(index) {
todo.completed = !todo.completed;
}
}
}
}
fn view(&self) -> Element<Message> {
// 构建输入区域
let input_area = row![
text_input("Add a new todo...", &self.new_todo)
.on_input(Message::NewTodoChanged)
.on_submit(Message::AddTodo)
.padding(10),
button("Add")
.on_press(Message::AddTodo)
.padding([10, 20]),
]
.spacing(10)
.align_items(Alignment::Center);
// 构建待办事项列表
let todos_list = if self.todos.is_empty() {
column![text("No todos yet!").size(16)]
} else {
column(
self.todos
.iter()
.enumerate()
.map(|(index, todo)| {
checkbox(
&todo.description,
todo.completed,
move |checked| {
if checked == todo.completed {
None
} else {
Some(Message::ToggleTodo(index))
}
},
)
.into()
})
.collect(),
)
.spacing(10)
};
// 组合所有组件
let content = column![
text("Todo App").size(24),
input_area,
scrollable(todos_list).height(Length::Fill),
text(format!("Total: {} items", self.todos.len())).size(14),
]
.spacing(20)
.padding(20)
.max_width(600);
container(content)
.width(Length::Fill)
.height(Length::Fill)
.center_x()
.center_y()
.into()
}
}
fn main() -> iced::Result {
TodoApp::run(Settings::default())
}
关键特性
- 跨平台支持:可在Windows、macOS和Linux上运行
- 响应式布局:内置灵活的布局系统
- 主题支持:可自定义应用外观
- 轻量级:不依赖复杂的运行时环境
- Elm架构:采用单向数据流模式
iced_widget是iced生态系统中的组件库部分,提供了构建现代化用户界面所需的各种组件。它结合了Rust的性能优势与直观的UI开发体验,适合需要本地GUI应用的场景。
1 回复
Rust UI工具库iced_widget的使用指南
介绍
iced_widget是Rust生态中一个轻量级、跨平台的GUI组件库,它是iced框架的核心部件集合。iced采用Elm架构模式,专注于简单性、类型安全性和跨平台兼容性,非常适合构建现代化的用户界面。
主要特点:
- 纯Rust实现,无外部依赖
- 响应式布局
- 跨平台支持(Windows/macOS/Linux/Web)
- 简洁易学的API设计
- 可定制的主题和样式
基本使用方法
添加依赖
首先在Cargo.toml中添加iced依赖:
[dependencies]
iced = { version = "0.10", features = ["widgets"] }
最小示例
use iced::widget::{button, column, text};
use iced::{Element, Sandbox, Settings};
struct Counter {
value: i32,
}
#[derive(Debug, Clone, Copy)]
enum Message {
Increment,
Decrement,
}
impl Sandbox for Counter {
type Message = Message;
fn new() -> Self {
Self { value: 0 }
}
fn title(&self) -> String {
String::from("Counter - Iced")
}
fn update(&mut self, message: Message) {
match message {
Message::Increment => self.value += 1,
Message::Decrement => self.value -= 1,
}
}
fn view(&self) -> Element<Message> {
column![
button("+").on_press(Message::Increment),
text(self.value).size(50),
button("-").on_press(Message::Decrement),
]
.padding(20)
.into()
}
}
fn main() -> iced::Result {
Counter::run(Settings::default())
}
常用组件示例
按钮(Button)
use iced::widget::button;
let my_button = button("Click me!")
.on_press(Message::ButtonClicked)
.padding(10);
文本(Text)
use iced::widget::text;
let title = text("Hello Iced!")
.size(24)
.style(iced::theme::Text::Color(iced::Color::from_rgb(1.0, 0.0, 0.0)));
输入框(TextInput)
use 极客d::widget::text_input;
let input = text_input("Placeholder", &self.input_value)
.on_input(Message::InputChanged)
.padding(10);
复选框(Checkbox)
use iced::widget::checkbox;
let checkbox = checkbox("Enable feature", self.is_checked)
.on_toggle(Message::CheckboxToggled);
滑动条(Slider)
use iced::widget::slider;
let slider = slider(0..=100, self.slider_value, Message::SliderChanged);
下拉选择(ComboBox)
use iced::widget::{combo_box, text};
let options = ["Option 1", "Option 2", "Option 3"];
let combo = combo_box(&options, Some(&self.selected_option), Message::OptionSelected);
布局示例
垂直布局(Column)
use iced::widget::column;
let content = column![
text("First item"),
text("Second item"),
text("Third item"),
]
.spacing(10)
.padding(20);
水平布局(Row)
use iced::widget::row;
let buttons = row![
button("Cancel"),
button("Save"),
]
.spacing(10);
滚动视图(Scrollable)
use iced::widget::{scrollable, text};
let scroll_content = scrollable(
column![
text("Long content item 1"),
// ...更多内容
text("Long content item 20"),
]
.width(iced::Length::Fill)
);
主题定制
use iced::theme;
// 应用自定义主题
impl Application for MyApp {
fn theme(&self) -> theme::Theme {
theme::Theme::custom(theme::Palette {
background: iced::Color::from_rgb(0.9, 0.9, 0.9),
text: iced::Color::from_rgb(极客.1, 0.1, 0.1),
primary: iced::Color::from_rgb(0.3, 0.6, 0.9),
success: iced::Color::from_rgb(0.2, 0.7, 0.2),
danger: iced::Color::from_rgb(0.8, 0.2, 0.2),
})
}
// ...
}
高级功能
自定义组件
use iced::widget::{container, text};
use iced::{Color, Length, Theme};
struct CustomWidget;
impl CustomWidget {
fn view<'a>(&self, message: &'a str) -> iced::Element<'a, Message> {
container(text(message))
.width(Length::Fill)
.height(Length::Units(100))
.center_x()
.center_y()
.style(theme::Container::Custom(Box::new(|theme| {
container::Appearance {
background: Some(iced::Background::Color(Color::from_rgb(0.8, 0.8, 1.0))),
border_radius: 10.0,
border_width: 2.0,
border_color: Color::BLACK,
..Default::default()
}
})))
.into()
}
}
异步操作
use iced::futures;
use iced::Command;
#[derive(Debug, Clone)]
enum Message {
StartLoading,
DataLoaded(Result<String, String>),
}
impl Sandbox for MyApp {
// ...
fn update(&mut self, message: Message) -> Command<Message> {
match message {
Message::StartLoading => Command::perform(
async {
// 模拟异步操作
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
Ok("Data loaded!".to_string())
},
Message::DataLoaded,
),
Message::DataLoaded(result) => {
self.data = result.unwrap_or_else(|e| e);
Command::none()
}
}
}
}
完整示例
下面是一个结合了多种组件的完整示例:
use iced::{
widget::{button, checkbox, column, combo_box, row, slider, text, text_input},
Element, Sandbox, Settings,
};
#[derive(Debug, Clone)]
enum Message {
ButtonClicked,
InputChanged(String),
CheckboxToggled(bool),
SliderChanged(u32),
OptionSelected(String),
}
struct MyApp {
input_value: String,
is_checked: bool,
slider_value: u32,
selected_option: String,
}
impl Sandbox for MyApp {
type Message = Message;
fn new() -> Self {
Self {
input_value: String::new(),
is_checked: false,
slider_value: 50,
selected_option: "Option 1".to_string(),
}
}
fn title(&self) -> String {
String::from("Iced Widget Demo")
}
fn update(&mut self, message: Message) {
match message {
Message::ButtonClicked => {
println!("Button clicked!");
}
Message::InputChanged(value) => {
self.input_value = value;
}
Message::CheckboxToggled(value) => {
self.is_checked = value;
}
Message::SliderChanged(value) => {
self.slider_value = value;
}
Message::OptionSelected(value) => {
self.selected_option = value;
}
}
}
fn view(&self) -> Element<Message> {
let options = ["Option 1", "Option 2", "Option 3"];
column![
text("Iced Widget Demo").size(24),
text_input("Enter text...", &self.input_value)
.on_input(Message::InputChanged)
.padding(10),
checkbox("Enable feature", self.is_checked)
.on_toggle(Message::CheckboxToggled),
slider(0..=100, self.slider_value, Message::SliderChanged),
combo_box(&options, Some(&self.selected_option), Message::OptionSelected),
row![
button("Cancel").on_press(Message::ButtonClicked),
button("Submit").on_press(Message::ButtonClicked),
]
.spacing(10),
text(format!("Slider value: {}", self.slider_value)),
text(format!("Selected option: {}", self.selected_option)),
]
.padding(20)
.spacing(10)
.into()
}
}
fn main() -> iced::Result {
MyApp::run(Settings::default())
}
总结
iced_widget提供了一套简洁而强大的组件库,使开发者能够轻松构建跨平台的GUI应用。通过组合基本组件和自定义样式,可以创建出既美观又功能丰富的用户界面。其响应式设计和Elm架构模式使得状态管理变得直观可靠。
对于更复杂的应用场景,iced还支持窗口定制、画布绘制、多线程等高级功能,是Rust生态中GUI开发的一个优秀选择。