Rust-GUI图形库:窗口显示Table表格且滑动条控制表格分隔线(3) 一、前置环境准备如前面两章环境一致二、创建项目Windows 打开 PowerShell / Linux/macOS 终端执行1. 创建二进制项目# 创建名为 table 的项目 cargo new table # 进入项目目录 cd table项目目录table/ ├── Cargo.toml # 项目配置、依赖管理 ├── Cargo.lock # 依赖版本锁定文件自动生成无需修改 ├── src/ │ └── main.rs # 全部业务代码窗口、逻辑、UI └── target/ # 编译产物目录自动生成 ├── debug/ # cargo run 开发编译文件 └── release/ # --release 发布成品程序2. 添加 Iced 依赖修改 Cargo.toml[package] name table version 0.1.0 edition 2021 # 依赖 Iced GUI 框架使用最新稳定版 [dependencies] iced 0.14说明iced 0.14会自动引入窗口、组件、渲染全套功能无需额外细分依赖。三、完整 src/main.rs整理带注释代码直接覆盖自动生成的src/main.rs#![cfg_attr(windows, windows_subsystem windows)] //! Iced Table 表格组件完整示例 //! 功能可调节内边距、分割线粗细的数据表格自带滚动、多列、文字状态色成功/警告/危险 //! Windows 编译后自动隐藏CMD黑色控制台窗口 // 字体权重相关 use iced::font; // 时间Duration工具时分快捷构造器 use iced::time::{Duration, hours, minutes}; // UI基础组件 use iced::widget::{ center_x, center_y, column, container, row, scrollable, slider, table, text, tooltip, }; // 布局对齐、填充、字体、文本右对齐、主题 use iced::{Center, Element, Fill, Font, Right, Theme}; /// 程序入口 pub fn main() - iced::Result { iced::application(Table::new, Table::update, Table::view) // 暗色Catppuccin摩卡主题 .theme(Theme::CatppuccinMocha) .run() } /// 全局应用状态结构体 struct Table { // 表格展示的数据源列表 events: VecEvent, // 单元格内边距 (水平padding, 垂直padding) padding: (f32, f32), // 行列分割线粗细 (竖线宽, 横线宽) separator: (f32, f32), } /// 所有UI交互消息枚举 #[derive(Debug, Clone)] enum Message { // 内边距滑块变化水平值、垂直值 PaddingChanged(f32, f32), // 分割线粗细滑块变化竖线、横线 SeparatorChanged(f32, f32), } impl Table { /// 初始化应用默认状态 fn new() - Self { Self { // 加载预设测试数据 events: Event::list(), // 默认单元格内边距左右10px上下5px padding: (10.0, 5.0), // 默认分割线粗细竖1px横1px separator: (1.0, 1.0), } } /// 状态更新逻辑接收消息修改参数 fn update(mut self, message: Message) { match message { Message::PaddingChanged(x, y) self.padding (x, y), Message::SeparatorChanged(x, y) self.separator (x, y), } } /// 构建完整页面UI fn view(self) - Element_, Message { // 构造表格组件 let table { // 工具闭包生成加粗表头文本 let bold |header| { text(header).font(Font { weight: font::Weight::Bold, ..Font::DEFAULT }) }; // 定义表格4列名称 / 时长 / 价格 / 评分 let columns [ // 第一列活动名称 table::column(bold(Name), |event: Event| text(event.name)), // 第二列活动时长超过90分钟标警告色文字右对齐垂直居中 table::column(bold(Time), |event: Event| { let minutes event.duration.as_secs() / 60; text!({minutes} min).style(if minutes 90 { text::warning } else { text::default }) }) .align_x(Right) .align_y(Center), // 第三列价格0免费绿色大于100标警告右对齐居中 table::column(bold(Price), |event: Event| { if event.price 0.0 { text!(${:.2}, event.price).style(if event.price 100.0 { text::warning } else { text::default }) } else { text(Free).style(text::success).width(Fill).center() } }) .align_x(Right) .align_y(Center), // 第四列评分4.7以上绿色成功2.0以下红色危险其余默认 table::column(bold(Rating), |event: Event| { text!({:.2}, event.rating).style(if event.rating 4.7 { text::success } else if event.rating 2.0 { text::danger } else { text::default }) }) .align_x(Right) .align_y(Center), ]; // 组装表格绑定内外边距、分割线参数 table(columns, self.events) .padding_x(self.padding.0) .padding_y(self.padding.1) .separator_x(self.separator.0) .separator_y(self.separator.1) }; // 底部控制面板两组滑块内边距、分割线 let controls { // 通用滑块行封装工具 // label: 标题, range: 数值范围, (当前x,y), on_change: 数值更新回调消息 let labeled_slider |label, range: std::ops::RangeInclusivef32, (x, y), on_change: fn(f32, f32) - Message| { row![ // 固定宽度标签 text(label).font(Font::MONOSPACE).size(14).width(100), // 水平参数滑块鼠标悬浮显示当前数值提示 tooltip( slider(range.clone(), x, move |x| on_change(x, y)), text!({x:.0}px).font(Font::MONOSPACE).size(10), tooltip::Position::Left ), // 垂直参数滑块 tooltip( slider(range, y, move |y| on_change(x, y)), text!({y:.0}px).font(Font::MONOSPACE).size(10), tooltip::Position::Right ), ] .spacing(10) .align_y(Center) }; // 垂直排列两组调节滑块 column![ labeled_slider(Padding, 0.0..30.0, self.padding, Message::PaddingChanged), labeled_slider( Separator, 0.0..5.0, self.separator, Message::SeparatorChanged ) ] .spacing(10) .width(400) }; // 页面整体布局上方滚动表格下方深色控制面板 column![ // 表格区域垂直居中、可滚动、内边距10 center_y(scrollable(center_x(table)).spacing(10)).padding(10), // 控制栏水平居中、深色背景容器 center_x(controls).padding(10).style(container::dark) ] .into() } } /// 表格单行数据模型活动信息 struct Event { name: String, // 活动名称 duration: Duration, // 持续时长 price: f32, // 价格 rating: f32, // 评分 0~5 } impl Event { /// 生成测试用活动数据列表 fn list() - VecSelf { vec![ Event { name: Get lost in a hacker bookstore.to_owned(), duration: hours(2), price: 0.0, rating: 4.9, }, Event { name: Buy vintage synth at Noisebridge flea market.to_owned(), duration: hours(1), price: 150.0, rating: 4.8, }, Event { name: Eat a questionable hot dog at 2AM.to_owned(), duration: minutes(20), price: 5.0, rating: 1.7, }, Event { name: Ride the MUNI for the story.to_owned(), duration: minutes(60), price: 3.0, rating: 4.1, }, Event { name: Scream into the void from Twin Peaks.to_owned(), duration: minutes(40), price: 0.0, rating: 4.9, }, Event { name: Buy overpriced coffee and feel things.to_owned(), duration: minutes(25), price: 6.5, rating: 4.5, }, Event { name: Attend an underground robot poetry slam.to_owned(), duration: hours(1), price: 12.0, rating: 4.8, }, Event { name: Browse cursed tech at a retro computer fair.to_owned(), duration: hours(2), price: 10.0, rating: 4.7, }, Event { name: Try to order at a secret ramen place with no sign.to_owned(), duration: minutes(50), price: 14.0, rating: 4.6, }, Event { name: Join a spontaneous rooftop drone rave.to_owned(), duration: hours(3), price: 0.0, rating: 4.9, }, Event { name: Sketch a stranger at Dolores Park.to_owned(), duration: minutes(45), price: 0.0, rating: 4.4, }, Event { name: Visit the Museum of Obsolete APIs.to_owned(), duration: hours(1), price: 9.99, rating: 4.2, }, Event { name: Chase the last working payphone.to_owned(), duration: minutes(35), price: 0.25, rating: 4.0, }, Event { name: Trade zines with a punk on BART.to_owned(), duration: minutes(30), price: 3.5, rating: 4.7, }, Event { name: Get a tattoo of the Git logo.to_owned(), duration: hours(1), price: 200.0, rating: 4.6, }, ] } }注#![cfg_attr(windows, windows_subsystem windows)]//加入上面一句! Windows 编译后自动隐藏CMD黑色控制台窗口四、运行项目1. 开发模式运行热编译、带日志cargo run首次运行会下载编译 Iced 及其底层图形依赖等待几分钟。 运行成功会弹出窗口。2. 运行窗口