0


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的官方代码:

userfd::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中导入:

userfd::FileDialog;

需要注意的是,FileDialog.pickfile()函数返回的是一个枚举类型Option,里面的数据就是文件的路径。
所以,我们可以使用Some来返回此路径。

ifletSome(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:

useiced::widget::{text, button,slider,column,image,container};

另外,我们在本系列第二篇提到过一个第三方的图像库Image,实际上iced中处理图像也用到了这个库,所以我们将Image也添加到依赖中:

image="0.24.7"

为了不混乱iced的image和第三方image,我们在导入第三方image时,如下:

externcrateimageas img_image;

当然,as后面的名字,你可以自己随便定义,只要你知道它是用来代替第三方image的“命名空间”即可。
image部件显示图像代码:

image(hd).content_fit(ContentFit::Fill),

此处,image函数的参数是一个Handle,官方关于image的源代码:

/// Creates a new [`Image`].////// [`Image`]: widget::Image#[cfg(feature = "image")]pubfnimage<Handle>(handle:implInto<Handle>)->crate::Image<Handle>{crate::Image::new(handle.into())}

所以,我们使用时,需要将图像文件转为Handle类型:

let hd=ifcfg!(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部件即可。

完整代码:

useiced::widget::{text, button,slider,column,row,image,container};useiced::{Alignment,Element,Length,Sandbox,Settings,ContentFit, alignment};useiced::window;useiced::window::icon;useiced::window::Position;useiced::Font;useiced::font::Family;externcrateimageas img_image;externcratenum_complex;userfd::FileDialog;pubfnmain()->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()})}pubstructCounter{
    srcimgpath:String,
    destimgpath:String,
    slivalue:f32,}#[derive(Debug, Clone,Copy)]pubenumMessage{OpenimgPressed,SaveimgPressed,SliderChanged(f32),}implSandboxforCounter{typeMessage=Message;fnnew()->Self{let path=String::new();Self{ srcimgpath: path.to_string(),//to_string()类似于clone
            destimgpath:path.to_string(),
            slivalue:0.0}}fntitle(&self)->String{String::from("iced_UI演示")}fnupdate(&mutself, message:Message){match message {Message::OpenimgPressed=>{ifletSome(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;}}}fnview(&self)->Element<Message>{let img_path=&self.srcimgpath;let hd=ifcfg!(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 开发语言

本文转载自: https://blog.csdn.net/normer123456/article/details/134602643
版权归原作者 机构师 所有, 如有侵权,请联系我们删除。

“Rust UI开发(三):iced如何打开图片(对话框)并在窗口显示图片?”的评论:

还没有评论