Rust UI开发(三):iced如何打开图片(对话框)并在窗口显示图片?
注:此文适合于对rust有一些了解的朋友
iced是一个跨平台的GUI库,用于为rust语言程序构建UI界面。

这是一个系列博文,本文是第三篇,前两篇的链接:
1、Rust UI开发(一):使用iced构建UI时,如何在界面显示中文字符
2、Rust UI开发(二):iced中如何为窗口添加icon图标
本篇是系列第三篇,主要关注如何在窗口上显示图片,要在窗口显示一张图片,基本上需要解决两个问题,一是图片文件导入,二是图片文件显示。这两个功能对于其他成熟语言都不是问题,文件对话框和图片渲染都不是难事,但iced是缺少对话框部件的。
所以,就要借助于第三方库,下面我们将针对这两个方面做说明。
实际窗口效果预览:

一 文件对话框
至少目前为止(iced=0.10)iced中没有集成对话框功能,包括文件对话框、字体、颜色、消息等对话框都没有,但我看到其他支持rust的GUI库如egui、nwg(native-window-gui)等都是有对话框的,当然egui中是用rfd库来实现的。
所以,在本篇中,我们也是利用rfd来实现文件对话框功能。

rfd是Rusty File Dialogs的简写,是跨平台的rust库,提供打开/保存对话框的功能。
rfd的官方代码:
use rfd::FileDialog;let files = FileDialog::new().add_filter("text", &["txt", "rs"]).add_filter("rust", &["rs", "toml"]).set_directory("/").pick_file();
使用起来也很简单,在你的项目的Cargo.toml中添加依赖:
rfd="0.12.1"
然后在main.rs中导入:
use rfd::FileDialog;
需要注意的是,FileDialog.pickfile()函数返回的是一个枚举类型Option,里面的数据就是文件的路径。
所以,我们可以使用Some来返回此路径。
if let Some(file)=FileDialog::new().set_directory("/").add_filter("all", &["*"]) //添加文件过滤,all是显示所有类型 .add_filter("文本文件(*txt)", &["txt", "rs"]) //只显示文本类型.add_filter("图像文件(*png*jpg*bmp)", &["png","jpg","jpeg","bmp"]) //只显示图像类型.set_title("打开图像").pick_file(){self.iamgepath=file.display().to_string();};
这样我们打开的图像的路径,就赋给了self.imagepath。
二 将图片显示在窗口界面上
我们现在已经得到了图像的路径,那么我们如何将图像显示在窗口上呢?这里需要用到iced提供的image这个功能,它是被定义为iced_widget的一个特性,即Features。Features是Rust中的一个概念,或者是一种机制。以下是rust官方手册关于Features的概念,大家自己理解一下。
- Cargo “features” provide a mechanism to express conditional compilation and optional dependencies.
- A package defines a set of named features in the [features] table of Cargo.toml, and each feature can either be enabled or disabled. Features for the package being built can be enabled on the command-line with flags such as --features. Features for dependencies can be enabled in the dependency declaration in Cargo.toml.
本篇说明一下如何使用image这个Features,在你的项目的Cargo.toml文件中,添加了iced依赖后,添加以下语句:
iced.features=["image"]
然后可以在main.rs中导入image:
use iced::widget::{text, button,slider,column,image,container};
另外,我们在本系列第二篇提到过一个第三方的图像库Image,实际上iced中处理图像也用到了这个库,所以我们将Image也添加到依赖中:
image="0.24.7"
为了不混乱iced的image和第三方image,我们在导入第三方image时,如下:
extern crate image as img_image;
当然,as后面的名字,你可以自己随便定义,只要你知道它是用来代替第三方image的“命名空间”即可。
image部件显示图像代码:
image(hd).content_fit(ContentFit::Fill),
此处,image函数的参数是一个Handle,官方关于image的源代码:
/// Creates a new [`Image`].
///
/// [`Image`]: widget::Image
#[cfg(feature = "image")]
pub fn image<Handle>(handle: impl Into<Handle>) -> crate::Image<Handle> {crate::Image::new(handle.into())
}
所以,我们使用时,需要将图像文件转为Handle类型:
let hd= if cfg!(target_arch = "wasm32") { //Wasm32是一种基于WebAssembly(Wasm)的32位虚拟机image::Handle::from_path("iced_test/src/img1.png")} else {//image::Handle::from_path("../iced_test/src/img2.jpeg")image::Handle::from_path(img_path)};
如上,使用image-Handle-from_path函数,从图像路径获取image的Handle,然后将此Handle传给image部件即可。
完整代码:
use iced::widget::{text, button,slider,column,row,image,container};
use iced::{Alignment, Element, Length,Sandbox, Settings, ContentFit, alignment};
use iced::window;
use iced::window::icon;
use iced::window::Position;
use iced::Font;
use iced::font::Family;
extern crate image as img_image;
extern crate num_complex;
use rfd::FileDialog;pub fn main() ->iced::Result{//Counter::run(Settings::default())let ff="微软雅黑";//第二种获取rgba图片的方法,利用Image库let img2=img_image::open("../iced_test/src/dota22.png"); let img2_path=match img2 {Ok(path)=>path,Err(error)=>panic!("error is {}",error),};let img2_file=img2_path.to_rgba8();let ico2=icon::from_rgba(img2_file.to_vec(), 64, 64);let ico2_file=match ico2{Ok(file)=>file,Err(error)=>panic!("error is {}",error),};Counter::run(Settings { window:window::Settings{ //设置窗口尺寸和位置及图标size:(800,600),position:Position::Specific(100, 40),icon:Some(ico2_file),..window::Settings::default()},default_font:Font{ //设置UI界面的显示字体family:Family::Name(ff),..Font::DEFAULT},..Settings::default()})
}pub struct Counter{srcimgpath:String,destimgpath:String,slivalue:f32,
}#[derive(Debug, Clone,Copy)]
pub enum Message {OpenimgPressed,SaveimgPressed,SliderChanged(f32),
}impl Sandbox for Counter {type Message = Message;fn new() -> Self {let path=String::new();Self { srcimgpath: path.to_string(), //to_string()类似于clonedestimgpath:path.to_string(),slivalue:0.0}}fn title(&self) -> String {String::from("iced_UI演示")}fn update(&mut self, message: Message) {match message {Message::OpenimgPressed => {if let Some(file)=FileDialog::new().set_directory("D:\\008 rustpro\\iced_test\\src").add_filter("all", &["*"]) //添加文件过滤,all是显示所有类型 .add_filter("文本文件(*txt)", &["txt", "rs"]) //只显示文本类型.add_filter("图像文件(*png*jpg*bmp)", &["png","jpg","jpeg","bmp"]) //只显示图像类型.set_title("打开图像").pick_file(){self.srcimgpath=file.display().to_string();};//println!("{:?}",file);}Message::SaveimgPressed=> {self.destimgpath="".to_string();}Message::SliderChanged(vl)=>{self.slivalue=vl;}}}fn view(&self) -> Element<Message> {let img_path=&self.srcimgpath;let hd= if cfg!(target_arch = "wasm32") { //Wasm32是一种基于WebAssembly(Wasm)的32位虚拟机image::Handle::from_path("iced_test/src/img1.png")} else {//image::Handle::from_path("../iced_test/src/img2.jpeg")image::Handle::from_path(img_path)};// let hd2= if cfg!(target_arch = "wasm32") { //Wasm32是一种基于WebAssembly(Wasm)的32位虚拟机// image::Handle::from_path("iced_test/src/img1.png")// } else {// image::Handle::from_path(img_path)// };//println!("hd is :{:?}",hd);container(column![row![//btn1button(text("打开图像").horizontal_alignment(alignment::Horizontal::Center).vertical_alignment(alignment::Vertical::Center).size(15)).on_press(Message::OpenimgPressed).padding(4),//btn2button(text("保存图像").horizontal_alignment(alignment::Horizontal::Center).vertical_alignment(alignment::Vertical::Center).size(15)).on_press(Message::SaveimgPressed).padding(4),].spacing(10).padding(10).align_items(Alignment::Start),//text:source image pathtext(format!("原图像路径:{:?}",self.srcimgpath)).size(15).horizontal_alignment(alignment::Horizontal::Center).vertical_alignment(alignment::Vertical::Center),row![text("图像尺寸调整:").size(15),//sliderslider(0.0..=100.0, self.slivalue, Message::SliderChanged).step(0.01).width(200),].spacing(20),//text:dest image pathtext(&self.destimgpath).size(15),row![image(hd).content_fit(ContentFit::Fill),//image(hd2).width(Length::Fixed(100.0)).height(Length::Fixed(100.0)).content_fit(ContentFit::Fill)].spacing(10).padding(10)].spacing(10) .padding(30).align_items(Alignment::Start)).into()}
}
以上代码中,不仅包含本篇涉及的内容,也包含前2篇中涉及的内容。
动态演示图:

相关文章:
Rust UI开发(三):iced如何打开图片(对话框)并在窗口显示图片?
注:此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库,用于为rust语言程序构建UI界面。 这是一个系列博文,本文是第三篇,前两篇的链接: 1、Rust UI开发(一):使用iced构建…...
网络爬虫(Python:Requests、Beautiful Soup笔记)
网络爬虫(Python:Requests、Beautiful Soup笔记) 网络协议简要介绍一。OSI参考模型二、TCP/IP参考模型对应关系TCP/IP各层实现的协议应用层传输层网络层 HTTP协议HTTP请求HTTP响应HTTP状态码 Requests(Python)Requests…...
【Kotlin】内联函数
文章目录 内联函数noinline: 避免参数被内联非局部返回使用标签实现Lambda非局部返回为什么要设计noinline crossinline具体化参数类型 Kotlin中的内联函数之所以被设计出来,主要是为了优化Kotlin支持Lambda表达式之后所带来的开销。然而,在Java中我们似…...
Unity技美35——再URP管线环境下,配置post后期效果插件(post processing)
前两年在我的unity文章第10篇写过,后效滤镜的使用,那时候大部分项目用的还是unity的基础管线,stander管线。 但是现在随着unity的发展,大部分项目都用了URO管线,甚至很多PC端用的都是高效果的HDRP管线,这就…...
Redis:持久化RDB和AOF
目录 概述RDB持久化流程指定备份文件的名称指定备份文件存放的目录触发RDB备份redis.conf 其他一些配置rdb的备份和恢复优缺点停止RDB AOF持久化流程AOF启动/修复/恢复AOF同步频率设置rewrite压缩原理触发机制重写流程no-appendfsync-on-rewrite 优缺点 如何选择 概述 Redis是…...
基于python协同过滤推荐算法的音乐推荐与管理系统
欢迎大家点赞、收藏、关注、评论啦 ,由于篇幅有限,只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 基于Python的协同过滤推荐算法的音乐推荐与管理系统是一个集成了音乐推荐和管理的系统,它使用协同过滤算…...
【极客技术】真假GPT-4?微调 Llama 2 以替代 GPT-3.5/4 已然可行!
近日小编在使用最新版GPT-4-Turbo模型(主要特点是支持128k输入和知识库截止日期是2023年4月)时,发现不同商家提供的模型回复出现不一致的情况,尤其是模型均承认自己知识库达到2023年4月,但当我们细问时,Fak…...
STK Components 二次开发-创建地面站
1.地面站只需要知道地面站的经纬高。 // Define the location of the facility using cartographic coordinates.var location new Cartographic(Trig.DegreesToRadians(-75.596766667), Trig.DegreesToRadians(40.0388333333), 0.0); 2.创建地面站 创建方式和卫星一样生成对…...
数据结构与算法(三)贪心算法(Java)
目录 一、简介1.1 定义1.2 基本步骤1.3 优缺点 二、经典示例2.1 选择排序2.2 背包问题 三、经典反例:找零钱3.1 题目3.2 解答3.3 记忆化搜索实现3.4 动态规划实现 一、简介 1.1 定义 贪心算法(Greedy Algorithm),又名贪婪法&…...
057-第三代软件开发-文件监视器
第三代软件开发-文件监视器 文章目录 第三代软件开发-文件监视器项目介绍文件监视器实现原理关于 QFileSystemWatcher实现代码 关键字: Qt、 Qml、 关键字3、 关键字4、 关键字5 项目介绍 欢迎来到我们的 QML & C 项目!这个项目结合了 QML&…...
二十七、微服务案例
目录 一、实现输入搜索功能 1、下载代码,在idea上打开 2、新建RequestParams类,用于接收解析请求 3、在启动类中加入客户端地址Bean,以便实现服务 4、编写搜索方法 5、新建返回分页结果类 6、实现搜索方法 7、编写控制类,…...
(C++)string类的模拟实现
愿所有美好如期而遇 前言 我们模拟实现string类不是为了去实现他,而是为了了解他内部成员函数的一些运行原理和时间复杂度,在将来我们使用时能够合理地去使用他们。 为了避免我们模拟实现的string类与全局上的string类冲突(string类也在std命名空间中)&…...
处理数据中的缺失值--删除缺少值的行
两个最主要的处理缺失值的方法是: ❏ 删除缺少值的行; ❏ 填充缺失值; 我们首先将serum_insulin的中的字段值0替换为None,可以看到缺失值的数量为374个; print(pima[serum_insulin].isnull().sum()) pima[serum_insu…...
Kotlin学习——kt里的集合,Map的各种方法之String篇
Kotlin 是一门现代但已成熟的编程语言,旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作,并提供了多种方式在多个平台间复用代码,以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…...
MIT 6.824 -- MapReduce Lab
MIT 6.824 -- MapReduce Lab 环境准备实验背景实验要求测试说明流程说明 实验实现GoLand 配置代码实现对象介绍协调器启动工作线程启动Map阶段分配任务执行任务 Reduce 阶段分配任务执行任务 终止阶段 崩溃恢复 注意事项并发安全文件转换golang 知识点 测试 环境准备 从官方gi…...
创新研报|顺应全球数字化,能源企业以“双碳”为目标的转型迫在眉睫
能源行业现状及痛点分析 挑战一:数字感知能力较弱 挑战二:与业务的融合度低 挑战三:决策响应速度滞后 挑战四:价值创造有待提升 挑战五:安全风险如影随形 能源数字化转型定义及架构 能源行业数字化转型体系大体…...
Blender 连续 5 天遭受大规模 DDoS 攻击
Blender 发布公告指出,在2023年11月18日至23日期间,blender.org 网站遭受了持续的分布式拒绝服务(DDoS)攻击,攻击者通过不断发送请求导致服务器超载,使网站运营严重中断。此次攻击涉及数百个 IP 地址的僵尸…...
Python 获取本地和广域网 IP
Python 获取本地IP ,使用第三方库,比如 netifaces import netifaces as nidef get_ip_address():try:# 获取默认网络接口(通常是 eth0 或 en0)default_interface ni.gateways()[default][ni.AF_INET][1]# 获取指定网络接口的IP地…...
静态路由配置过程
静态路由 静态路由简介 路由器在转发数据时,要先在路由表(Routing Table)中在找相应的路由,才能知道数据包应该从哪个端口转发出去。路由器建立路由表基本上有以下三种途径。 (1)直连路由:路由…...
基于OGG实现MySQL实时同步
📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
