如何把Rust的 iced从 0.12升级到0.14?
我在iced 0.12中有这段能够正常工作的代码,现在想把它升级到iced 0.14。
use iced::widget::{container, text};
use iced::{Application, Color, Command, Element, Settings, Subscription, Theme};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
#[derive(Debug, Clone)]
pub(crate) enum Message {
ColorChanged(ColorState),
}
#[derive(Debug, Clone, Copy, PartialEq)]
enum ColorState {
Red,
Orange,
Green,
}
impl ColorState {
fn next(self) -> Self {
match self {
ColorState::Red => ColorState::Orange,
ColorState::Orange => ColorState::Green,
ColorState::Green => ColorState::Red,
}
}
fn to_color(self) -> Color {
match self {
ColorState::Red => Color::from_rgb(0.8, 0.0, 0.0),
ColorState::Orange => Color::from_rgb(1.0, 0.5, 0.0),
ColorState::Green => Color::from_rgb(0.0, 0.8, 0.0),
}
}
fn to_text(self) -> &'static str {
match self {
ColorState::Red => "Red",
ColorState::Orange => "Orange",
ColorState::Green => "Green",
}
}
}
struct ColorCycleApp {
current_color: ColorState,
color_state: Arc<Mutex<ColorState>>,
}
impl Application for ColorCycleApp {
type Message = Message;
type Theme = Theme;
type Executor = iced::executor::Default;
type Flags = ();
fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) {
let color_state = Arc::new(Mutex::new(ColorState::Red));
// Start the background thread
let color_state_clone = Arc::clone(&color_state);
thread::spawn(move || {
loop {
thread::sleep(Duration::from_secs(2));
let mut state = color_state_clone.lock().unwrap();
*state = state.next();
println!("Thread changed color to: {:?}", *state);
}
});
(
Self {
current_color: ColorState::Red,
color_state,
},
Command::none(),
)
}
fn title(&self) -> String {
String::from("My GUI")
}
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
match message {
Message::ColorChanged(new_color) => {
self.current_color = new_color;
println!("New color: {:?}", new_color);
Command::none()
}
}
}
fn view(&'_ self) -> Element<'_, Self::Message> {
let current_color = self.current_color.to_color();
let label = text(self.current_color.to_text()).size(48);
let colored_container = container(label)
.width(iced::Length::Fill)
.height(iced::Length::Fill)
.center_x()
.center_y()
.style(move |_theme: &Theme| container::Appearance {
background: Some(iced::Background::Color(current_color)),
..Default::default()
});
colored_container.into()
}
fn subscription(&self) -> Subscription<Self::Message> {
let color_state = Arc::clone(&self.color_state);
iced::subscription::unfold("color_monitor", ColorState::Red, move |last_color| {
let color_state = Arc::clone(&color_state);
async move {
loop {
std::thread::sleep(Duration::from_millis(100));
let current_color = {
let state = color_state.lock().unwrap();
*state
};
if current_color != last_color {
return (Message::ColorChanged(current_color), current_color);
}
}
}
})
}
}
fn main() -> iced::Result {
ColorCycleApp::run(Settings {
window: iced::window::Settings {
size: iced::Size::new(400.0, 300.0),
..Default::default()
},
..Default::default()
})
}
我遇到4 个错误。
- 未解析的导入
iced::Command(Rust给出的建议是std::process::Command或 tokio::process::Command) - 无法解析:在
iced中找不到subscription - 找不到模块
container中的结构体、变体或联合类型Appearance - 预期为trait,但找到了结构体
Application
到目前为止,我尝试了使用iced:Program(用于处理Application)以及使用Container:Style代替Appearance,但还没走到那一步。
解决方案
这是修复后的版本:
use iced::{
Color, Element, Length, Subscription, Task, Theme,
widget::{container, text},
};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
#[derive(Debug, Clone)]
pub(crate) enum Message {
ChangeColor,
}
#[derive(Debug, Clone, Copy, PartialEq)]
enum ColorState {
Red,
Orange,
Green,
}
impl ColorState {
fn next(self) -> Self {
match self {
ColorState::Red => ColorState::Orange,
ColorState::Orange => ColorState::Green,
ColorState::Green => ColorState::Red,
}
}
fn to_color(self) -> Color {
match self {
ColorState::Red => Color::from_rgb(0.8, 0.0, 0.0),
ColorState::Orange => Color::from_rgb(1.0, 0.5, 0.0),
ColorState::Green => Color::from_rgb(0.0, 0.8, 0.0),
}
}
fn to_text(self) -> &'static str {
match self {
ColorState::Red => "Red",
ColorState::Orange => "Orange",
ColorState::Green => "Green",
}
}
}
struct ColorCycleApp {
current_color: ColorState,
color_state: Arc<Mutex<ColorState>>,
}
impl ColorCycleApp {
fn new() -> Self {
let color_state = Arc::new(Mutex::new(ColorState::Red));
// Start the background thread
let color_state_clone = Arc::clone(&color_state);
thread::spawn(move || {
loop {
thread::sleep(Duration::from_secs(2));
let mut state = color_state_clone.lock().unwrap();
*state = state.next();
println!("Thread changed color to: {:?}", *state);
}
});
Self {
current_color: ColorState::Red,
color_state,
}
}
fn title(&self) -> String {
String::from("My GUI")
}
fn update(&mut self, message: Message) -> Task<Message> {
match message {
Message::ChangeColor => {
let new_color = *self.color_state.lock().unwrap();
if self.current_color != new_color {
self.current_color = new_color;
println!("New color: {:?}", new_color);
}
Task::none()
}
}
}
fn view(&'_ self) -> Element<'_, Message> {
let current_color = self.current_color.to_color();
let label = text(self.current_color.to_text()).size(48);
let colored_container = container(label)
.width(iced::Length::Fill)
.height(iced::Length::Fill)
.center(Length::Fill)
.style(move |_theme: &Theme| container::Style {
background: Some(iced::Background::Color(current_color)),
..Default::default()
});
colored_container.into()
}
fn subscription(&self) -> Subscription<Message> {
iced::time::every(Duration::from_millis(100)).map(|_| Message::ChangeColor)
}
}
fn main() -> iced::Result {
iced::application(
ColorCycleApp::new,
ColorCycleApp::update,
ColorCycleApp::view,
)
.subscription(ColorCycleApp::subscription)
.title(ColorCycleApp::title)
.window(iced::window::Settings {
size: (400.0, 300.0).into(),
..Default::default()
})
.run()
}
它需要 tokio 功能:
[dependencies]
iced = { version = "0.14", features = ["tokio"] }
解释
iced::Command未找到。
iced::Command大致被iced::Task取代,过程中有一些小的变动。iced::subscription无法解析。
虽然iced::subscription模块被移除了,但iced::Subscription仍然存在于根模块中。然而iced::subscription::unfold也被移除了,因此需要大幅重构上文所示的订阅逻辑。iced::widget::container::Appearance未找到。
iced::widget::container::Appearance结构体本质上被重命名为iced::widget::container::Style,并新增了snap字段。- 预期的trait,找到了结构体
Application。
iced::application::Applicationtrait已被移除,相应地,主应用程序结构体需要的方法应当「自由地定义」(如上所示)。iced 0.14中的Application结构体仍然提供关于应用可用内容的一些指引。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。