本文将详细介绍基于 iced 实现一个时钟的完整示例。
知识点
- iced 的 subscription
- 窗口图标
- 程序图标
- 自定义字体
- 打包优化
- 在 release 版本中,防止在 Windows 上出现额外的控制台窗口
预览
UI
优化后的文件大小
开发环境
- 系统:Windows 11 专业版
- 编辑器:Visual Studio Code
- cargo:1.85.1 (d73d2caf9 2024-12-31)
- 编译工具链:stable-x86_64-pc-windows-msvc (active, default)
代码
Cargo.toml
[package]
name = "clock"
version = "0.0.1"
edition = "2024"
build = "build.rs"
[dependencies]
chrono = "0.4.41" # 时间格式化
iced = { version = "0.13.1", features = ["image", "tokio"] } # image 特性是为了导入窗口图标。tokio 是为了启用 iced::time 定时器
[build-dependencies]
winres = "0.1.12" # 为可执行文件添加元信息和图标
[profile.release]
strip = true
lto = true
opt-level = "z"
build.rs
extern crate winres;
fn main() {
if cfg!(target_os = "windows") {
let mut res = winres::WindowsResource::new();
res.set_icon("res/icon.ico");
res.compile().unwrap();
}
}
main.rs
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use std::time::Duration;
use chrono::Local;
use iced::{
Element, Font, Length, Size, Subscription,
widget::{column, container, text},
window::{Icon, Settings, icon},
};
#[derive(Default)]
struct ClockApp {
current_time: String,
}
#[derive(Debug, Clone, Copy)]
pub enum Message {
Tick,
}
impl ClockApp {
pub fn view(&self) -> Element<Message> {
container(column![text(&self.current_time).size(26),])
.center(Length::Fill)
.into()
}
pub fn update(&mut self, message: Message) {
match message {
Message::Tick => {
let now = Local::now();
self.current_time =
format!("{} {}", now.format("%Y-%m-%d"), now.format("%H:%M:%S"));
}
}
}
fn subscription(&self) -> Subscription<Message> {
iced::time::every(Duration::from_millis(1000)).map(|_| Message::Tick)
}
}
fn main() -> iced::Result {
iced::application("Clock", ClockApp::update, ClockApp::view)
.font(include_bytes!("../res/MapleMono-Regular.ttf"))
.default_font(Font::with_name("Maple Mono"))
.window(Settings {
icon: Some(Icon::from(
icon::from_file_data(include_bytes!("../res/icon.ico"), None).unwrap(),
)),
size: Size::new(400.0, 200.0),
..Default::default()
})
.subscription(ClockApp::subscription)
.run()
}
注: icon.ico 宽高是 256px * 256px
参考
https://zhuanlan.zhihu.com/p/16785239921
https://crates.io/crates/winres
https://crates.io/crates/chrono
https://docs.rs/iced/latest/iced/index.html#passive-subscriptions