Rust-GUI图形库:多窗口显示multi_window(4)
一、前置环境准备如前面两章环境一致二、创建项目Windows 打开 PowerShell / Linux/macOS 终端执行1. 创建二进制项目# 创建名为 multi_window 的项目 cargo new multi_window # 进入项目目录 cd multi_window项目目录multi_window/ ├── Cargo.toml # 项目配置、依赖管理 ├── Cargo.lock # 依赖版本锁定文件自动生成无需修改 ├── src/ │ └── main.rs # 全部业务代码窗口、逻辑、UI └── target/ # 编译产物目录自动生成 ├── debug/ # cargo run 开发编译文件 └── release/ # --release 发布成品程序2. 添加 Iced 依赖修改 Cargo.toml[package] name multi_window 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)] // Windows平台编译后隐藏CMD黑色控制台窗口 // Iced 基础UI组件 use iced::widget::{ button, center, center_x, column, container, operation, scrollable, space, text, text_input, }; // 多窗口操作相关API use iced::window; // 布局、元素、填充、消息映射、订阅、异步任务、主题、坐标向量 use iced::{Center, Element, Fill, Function, Subscription, Task, Theme, Vector}; // 有序哈希表用来按窗口ID存储多个窗口数据 use std::collections::BTreeMap; /// 程序入口使用 daemon 模式支持多窗口常驻程序 fn main() - iced::Result { iced::daemon(Example::new, Example::update, Example::view) // 全局事件订阅监听窗口关闭 .subscription(Example::subscription) // 根据窗口ID动态获取窗口标题 .title(Example::title) // 根据窗口ID动态切换窗口主题 .theme(Example::theme) // 根据窗口ID动态设置窗口缩放比例 .scale_factor(Example::scale_factor) .run() } /// 程序根状态统一管理所有打开的子窗口 struct Example { // key: 窗口唯一ID value: 单个窗口的独立配置数据 windows: BTreeMapwindow::Id, Window, } /// 单个窗口独立配置数据 #[derive(Debug)] struct Window { // 窗口标题文本 title: String, // 缩放输入框临时文本未提交 scale_input: String, // 当前生效的窗口缩放系数 current_scale: f32, // 窗口独立主题每个窗口可以明暗/配色不同 theme: Theme, } /// 全部交互消息枚举涵盖窗口创建、关闭、输入框修改、缩放提交 #[derive(Debug, Clone)] enum Message { // 点击新建窗口按钮 OpenWindow, // 新窗口创建完成携带窗口ID WindowOpened(window::Id), // 窗口被关闭携带窗口ID WindowClosed(window::Id), // 缩放输入框实时输入变更 ScaleInputChanged(window::Id, String), // 缩放输入框回车提交应用缩放 ScaleChanged(window::Id, String), // 窗口标题输入框实时修改 TitleChanged(window::Id, String), } impl Example { /// 程序初始化创建初始第一个窗口 fn new() - (Self, TaskMessage) { // 发起打开窗口异步任务 let (_, open_task) window::open(window::Settings::default()); ( Self { windows: BTreeMap::new(), }, // 窗口创建完成后发送 WindowOpened 消息 open_task.map(Message::WindowOpened), ) } /// 根据窗口ID读取对应窗口标题供窗口标题渲染回调使用 fn title(self, window: window::Id) - String { self.windows .get(window) .map(|win| win.title.clone()) .unwrap_or_default() } /// 消息更新核心逻辑处理所有窗口增删、参数修改 fn update(mut self, message: Message) - TaskMessage { match message { // 点击新建窗口按钮 Message::OpenWindow { // 没有已存在窗口则直接返回不创建 let Some(last_win_id) self.windows.keys().last() else { return Task::none(); }; // 获取上一个窗口坐标新窗口偏移20px避免完全重叠 window::position(last_win_id) .then(|last_pos_opt| { let new_pos last_pos_opt.map_or(window::Position::Default, |last_pos| { window::Position::Specific(last_pos Vector::new(20.0, 20.0)) }); // 打开新窗口携带偏移坐标 let (_, open_task) window::open(window::Settings { position: new_pos, ..window::Settings::default() }); open_task }) .map(Message::WindowOpened) } // 新窗口创建完成初始化窗口配置并自动聚焦标题输入框 Message::WindowOpened(win_id) { // 根据当前窗口总数生成新窗口默认配置 let new_win Window::new(self.windows.len() 1); // 存入窗口映射表 self.windows.insert(win_id, new_win); // 自动聚焦当前窗口的标题输入框 operation::focus(format!(input-{win_id})) } // 窗口关闭删除窗口数据无窗口时退出整个程序 Message::WindowClosed(win_id) { self.windows.remove(win_id); if self.windows.is_empty() { iced::exit() } else { Task::none() } } // 缩放输入框实时输入仅更新临时文本不生效 Message::ScaleInputChanged(win_id, text) { if let Some(win) self.windows.get_mut(win_id) { win.scale_input text; } Task::none() } // 缩放输入回车提交解析数值并限制范围0.5~5.0更新生效缩放 Message::ScaleChanged(win_id, input_text) { if let Some(win) self.windows.get_mut(win_id) { win.current_scale input_text .parse::f32() // 解析失败保留原有缩放值 .unwrap_or(win.current_scale) .clamp(0.5, 5.0); } Task::none() } // 标题输入框实时修改同步更新窗口标题 Message::TitleChanged(win_id, new_title) { if let Some(win) self.windows.get_mut(win_id) { win.title new_title; } Task::none() } } } /// 单窗口渲染函数每个独立窗口都会单独调用此view fn view(self, window_id: window::Id) - Element_, Message { // 根据窗口ID取出对应窗口数据绘制内容无数据返回空白占位 if let Some(win) self.windows.get(window_id) { center(win.view(window_id)).into() } else { space().into() } } /// 根据窗口ID获取对应窗口专属主题 fn theme(self, window_id: window::Id) - OptionTheme { Some(self.windows.get(window_id)?.theme.clone()) } /// 根据窗口ID获取当前窗口缩放系数 fn scale_factor(self, window_id: window::Id) - f32 { self.windows .get(window_id) .map(|win| win.current_scale) .unwrap_or(1.0) } /// 全局订阅监听所有窗口关闭事件转化为消息 fn subscription(self) - SubscriptionMessage { window::close_events().map(Message::WindowClosed) } } impl Window { /// 创建单个窗口默认配置 fn new(count: usize) - Self { Self { title: format!(Window_{count}), scale_input: 1.0.to_string(), current_scale: 1.0, // 循环取用内置全部主题每个窗口主题不一样 theme: Theme::ALL[count % Theme::ALL.len()].clone(), } } /// 单个窗口内部UI布局 fn view(self, id: window::Id) - Element_, Message { // 缩放输入区域文字提示 输入框回车提交缩放 let scale_input_area column![ text(Window scale factor:), text_input(Window Scale, self.scale_input) // 输入实时更新临时文本 .on_input(Message::ScaleInputChanged.with(id)) // 按下回车提交缩放数值 .on_submit(Message::ScaleChanged(id, self.scale_input.to_string())) ]; // 窗口标题输入区域绑定唯一ID用于自动聚焦 let title_input_area column![ text(Window title:), text_input(Window Title, self.title) .on_input(Message::TitleChanged.with(id)) .id(format!(input-{id})) ]; // 新建窗口按钮 let btn_new_window button(text(New Window)).on_press(Message::OpenWindow); // 垂直布局所有控件间距50宽度200水平居中 let content column![scale_input_area, title_input_area, btn_new_window] .spacing(50) .width(Fill) .align_x(Center) .width(200); // 外层滚动容器内边距包裹内容 container(scrollable(center_x(content))).padding(10).into() } }注#![cfg_attr(windows, windows_subsystem windows)]//加入上面一句! Windows 编译后自动隐藏CMD黑色控制台窗口四、运行项目1. 开发模式运行热编译、带日志cargo run首次运行会下载编译 Iced 及其底层图形依赖等待几分钟。 运行成功会弹出窗口。2. 运行窗口

相关新闻

在 Kapa 的技术知识库问答场景中,他们接入了技术文档、API 参考、PDF、

在 Kapa 的技术知识库问答场景中,他们接入了技术文档、API 参考、PDF、

论坛以及支持工单等多种资料,并作为检索上下文提供给 AI 助手。 这个工作流程是:Retriever(检索系统)先从知识库中检索出候选 chunk,Reranker 会根据问题相关性,对检索到的候选 chunk 重新排序,…

2026/7/19 4:45:57 阅读更多 →
Unreal引擎集成TypeScript开发指南:Puerts原理、配置与双向调用实践

Unreal引擎集成TypeScript开发指南:Puerts原理、配置与双向调用实践

1. 项目概述:为什么要在Unreal里搞TypeScript?如果你是一个常年混迹在Unreal引擎和前端开发两个圈子的开发者,看到“Puerts”这个名字,大概率会眼前一亮。这玩意儿说白了,就是给Unreal引擎这个庞然大物,开了…

2026/7/19 4:45:57 阅读更多 →
sif不拆变体实现流量翻倍!sif优惠码开通sif关键词工具

sif不拆变体实现流量翻倍!sif优惠码开通sif关键词工具

sif不拆变体实现流量翻倍!sif优惠码开通sif关键词工具不拆变体,自然流量也能翻倍!这不是简单的测试,而是成熟且广泛的应用!开通输入sif折扣码:KJYH 开通即可原因如下:目前80%的关键词都有多个变…

2026/7/19 4:44:56 阅读更多 →

最新新闻

GitHub 访问加速技术方案:基于 hosts 文件优化的 DNS 解析优化系统

GitHub 访问加速技术方案:基于 hosts 文件优化的 DNS 解析优化系统

GitHub 访问加速技术方案:基于 hosts 文件优化的 DNS 解析优化系统 【免费下载链接】github-hosts 🔥🔥🔥 本项目定时更新GitHub最新hosts,解决GitHub图片无法显示,加速GitHub网页浏览。 项目地址: https…

2026/7/20 12:12:07 阅读更多 →
AIPS系统如何解决企业数据孤岛问题

AIPS系统如何解决企业数据孤岛问题

1. 为什么企业系统越多数据越乱?这个问题困扰着太多数字化转型中的企业。我见过不少公司上了ERP、CRM、MES、WMS等各类系统后,反而出现了更严重的数据孤岛问题。采购说库存不准,生产说计划不对,销售说预测失真,各部门都…

2026/7/20 12:12:07 阅读更多 →
PRU-ICSS核心寄存器配置实战:从手册到工业实时系统

PRU-ICSS核心寄存器配置实战:从手册到工业实时系统

1. 项目概述:从寄存器手册到实战配置如果你和我一样,长期在工业自动化、电机控制或者实时通信领域摸爬滚打,那你一定对德州仪器(TI)的PRU-ICSS(Programmable Real-Time Unit and Industrial Communication …

2026/7/20 12:12:07 阅读更多 →
Qt跨平台开发实战:Windows与Ubuntu环境差异解析

Qt跨平台开发实战:Windows与Ubuntu环境差异解析

1. 跨平台Qt开发环境差异全解析最近在Windows 11和Ubuntu 26.04上同时进行Qt项目开发时,发现两个平台的表现差异远超预期。作为长期使用Qt的开发者,我整理了这份避坑指南,帮助大家规避跨平台开发中的常见陷阱。2. 环境准备与基础配置对比2.1 …

2026/7/20 12:12:07 阅读更多 →
Cocos2.X Android输入框适配:解决软键盘顶起画面与触摸错位问题

Cocos2.X Android输入框适配:解决软键盘顶起画面与触摸错位问题

1. 项目概述与问题根源剖析做Cocos2.X原生游戏开发,特别是需要接入用户登录、聊天、支付等功能的项目,Android端输入框的适配绝对是个绕不开的“坑”。我遇到过不止一个项目,在游戏内弹出输入框(比如输入兑换码、聊天打字&#xf…

2026/7/20 12:12:07 阅读更多 →
掌握RAG技术:小白程序员也能轻松搭建大模型知识库问答系统(收藏版

掌握RAG技术:小白程序员也能轻松搭建大模型知识库问答系统(收藏版

本文从零基础概念讲起,详细介绍了RAG(Retrieval-Augmented Generation)技术栈在大模型知识库问答系统中的应用。涵盖文本切分、向量模型选型、向量数据库选择、检索召回策略以及大模型选型等核心组件的选型逻辑,并提供可直接运行的…

2026/7/20 12:11:05 阅读更多 →

日新闻

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

2026 WAIC:努比亚二代“豆包手机”NaviX Ultra亮相,智能体验全面升级!

7月18日智东西消息,在2026 WAIC期间,努比亚联合字节豆包打造的二代“豆包手机”努比亚NaviX Ultra首次亮相,相比一代有诸多升级。智能体手机理念中兴通讯终端事业部总裁、努比亚总裁倪飞表示,智能体手机要从人操作手机变为手机帮人…

2026/7/20 0:00:34 阅读更多 →
努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra亮相WAIC,智能体手机能否让用户生活更简单?

努比亚NaviX Ultra:外观与功能双升级在2026 WAIC期间,首次亮相的努比亚NaviX Ultra吸引了众多目光。它是努比亚联合字节豆包打造的二代“豆包手机”,与一代努比亚M153相比,外观设计变化较大。其机身背部搭载横向排布的大尺寸影像模…

2026/7/20 0:00:34 阅读更多 →
C# 将逗号分割的字符串转换为long,并添加到List<long>

C# 将逗号分割的字符串转换为long,并添加到List<long>

目录 方法1:使用Split和Convert.ToInt64 方法2:使用LINQ的Select和ToList 方法3:使用TryParse进行异常安全转换(推荐) 如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天…

2026/7/20 0:00:34 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/20 5:57:49 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/20 4:31:26 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/20 5:56:42 阅读更多 →

月新闻