本文介绍: iced一个平台的GUI库,用于rust语言程序构建UI界面。这是一个系列博文本文第三篇,前两篇的链接:1、2、本篇系列第三篇,主要关注如何窗口显示图片,要在窗口显示一张图片基本需要解决两个问题,一是图片文件导入,二是图片文件显示。这两个功能对于其他成熟语言都不是问题文件对话框图片渲染都不是难事,但iced是缺少对话框部件的。所以,就要借助于第三方库,下面我们针对两个方面做说明

注:此文适合于对rust有一些了解的朋友
iced一个跨平台的GUI库,用于rust语言程序构建UI界面
在这里插入图片描述

这是一个系列博文本文第三篇,前两篇的链接:
1、Rust UI开发(一):使用iced构建UI时,如何在界面显示中文字符
2、Rust UI开发(二):iced中如何为窗口添加icon图标

本篇系列第三篇,主要关注如何窗口显示图片,要在窗口显示一张图片基本需要解决两个问题,一是图片文件导入,二是图片文件显示。这两个功能对于其他成熟语言都不是问题,文件对话框和图片渲染都不是难事,但iced是缺少对话部件的。

所以,就要借助于第三方库,下面我们针对两个方面做说明
实际窗口效果预览
在这里插入图片描述

一 文件对话

至少目前为止(iced=0.10)iced没有集成对话功能,包括文件对话框、字体、颜色、消息对话框都没有,但我看到其他支持rust的GUI库如eguinwgnativewindowgui)等都是有对话框的,当然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概念大家自己理解一下。

本篇说明一下如何使用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()类似于clone
            destimgpath:path.to_string(),
            slivalue:0.0}
    }

    fn title(&amp;self) -> String {
        String::from("iced_UI演示")
    }

    fn update(&amp;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", &amp;["*"])                  //添加文件过滤,all是显示所有类型 
            .add_filter("文本文件(*txt)", &amp;["txt", "rs"])           //只显示文本类型
            .add_filter("图像文件(*png*jpg*bmp)", &amp;["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(&amp;self) -> Element<Message> {
       
        let img_path=&amp;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![
             //btn1
             button(text("打开图像")
             .horizontal_alignment(alignment::Horizontal::Center)
             .vertical_alignment(alignment::Vertical::Center)
             .size(15)
             ).on_press(Message::OpenimgPressed)
             .padding(4),
             //btn2
             button(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 path
            text(format!("原图像路径:{:?}",self.srcimgpath)).size(15)
            .horizontal_alignment(alignment::Horizontal::Center)
            .vertical_alignment(alignment::Vertical::Center),
            row![
                text("图像尺寸调整:").size(15),
                //slider
                slider(0.0..=100.0, self.slivalue, Message::SliderChanged).step(0.01).width(200),
            ].spacing(20),
         
            //textdest image path
            text(&amp;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篇中涉及的内容

动态演示图:
在这里插入图片描述

原文地址:https://blog.csdn.net/normer123456/article/details/134602643

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_15415.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注