[rustGUI][iced]基于rust的GUI库iced(0.13)的部件学习(06):基于iced实 ...

打印 上一主题 下一主题

主题 897|帖子 897|积分 2691

媒介

本文是关于iced库的部件介绍,iced库是基于rust的GUI库,作者自述是受Elm开导。
iced现在的版本是0.13.1,相较于此前的0.12版本,有较大改动。
本合集是基于新版本的关于分部件(widget)的使用介绍,包括源代码介绍、实例使用等。
环境配置

系统:window10
平台:visual studio code
语言:rust
库:iced 0.13
扩展库:iced_aw
概述

图片欣赏器的实现,我们的假想是可以通过文件夹导入所有图片,然后获取的图片在界面上排布显示,此中有一个是主图片,其他图片以缩略图形式在下方,可以通过按钮切换图片的显示。
前提条件
为了实现文件夹导入,必要添加一个对话框库,即RFD:

1、新建iced项目

关于如何新建iced窗口并设置窗口参数,可以参考博文:
基于rust的GUI库iced的学习(00):一个典范的iced窗口的实现
本文不再赘述。
本文的目的是创建一个能够导入图片并进行欣赏的窗口,所以我们必要先添加以下模块:
  1. rfd = "0.15.2"
  2. image = "0.25.5"
复制代码
我们的窗口基本布局如下:

如图,通过导入文件夹按钮导入图片文件夹,获取了图片列表后,在窗口动态添加并显示,而上一张下一张按钮则可以切换图片的显示。
我们先来看view函数的基本布局:
  1. let img_main_h=image::Handle::from_path(&self.img_main_p);
  2.         
  3.         //let img_main= image(self.handle.clone());
  4.         let img_main = image(img_main_h).width(300).height(300)
  5.                                 .content_fit(iced::ContentFit::Contain);
  6.         let img_sub_view = self.updateview();
  7.         let cont1=container(
  8.     column![
  9.                 row![
  10.                     //button(text("打开").size(20)).width(80).on_press(Message::Open),
  11.                     button(text("导入文件夹").size(14)).width(100).on_press(Message::OpenFolder),
  12.                 ],
  13.                 row![
  14.                     button(text("上一张").size(14)).width(100).on_press(Message::Last),
  15.                     button(text("下一张").size(14)).width(100).on_press(Message::Next),
  16.                 ].spacing(10),
  17.                 img_main,
  18.                 img_sub_view,
  19.                
  20.             ].padding(10).spacing(10).align_x(Center)
  21.         ).align_x(Center)
  22.         .align_y(Center)
  23.         .width(iced::Length::Fill).height(iced::Length::Fill)
  24.         .style(|t| styles::mycontainerstyle(t));
  25.         cont1.into()
复制代码
上面的代码中,updateview函数如下:
  1. fn updateview(&self) ->Column<Message>{
  2.         let row1 = match self.imgs.len() {
  3.             0 => Self::contcont("无图片"),
  4.             n => {
  5.                 //println!("图片数量:{}",n);
  6.                 let mut row1 = row![].spacing(20);
  7.                 for i in 0..n {
  8.                     row1 = row1.push(
  9.                         container(
  10.                         image(image::Handle::from_path(self.imgs[i].display().to_string())).width(100).height(100)
  11.                         ).style(move |t| styles::mycontainerstyle_border(t,i.to_string(),self.current_index))
  12.                     );
  13.                 };
  14.                 Self::contcont("图片列表").push(row1)
  15.             },
  16.         };
  17.         row1
  18.     }
复制代码
为什么要使用这个函数,重要目的是为了动态添加图片元素,这个函数会根据获取的图片数量,生成相应的image元素并显示在窗口(假如图片太多则会非常卡,本文未作优化)。
2、文件夹导入和遍历

在iced中,文件夹导入,我们使用rfd库来创建对话框:
  1. if let Some(folder) = FileDialog::new()
  2.                                         .set_directory("E:\\100rust2\\iced-img")
  3.                                         .set_title("打开文件夹")
  4.                                         .pick_folder() {
  5.                                             println!("打开文件夹: {:?}", folder);
  6.                                             let paths = folderbrowser(folder).unwrap();
  7.                                             if paths.len() > 0 {
  8.                                                 self.imgs.clear();
  9.                                                 self.current_index = 0;
  10.                                                 for path in paths {
  11.                                                     println!("文件夹中的文件: {:?}", path);
  12.                                                     self.imgs.push(path);
  13.                                                 };
  14.                                                 self.img_main_p = self.imgs[self.current_index].display().to_string();
  15.                                             } else {
  16.                                                 MessageDialog::new()
  17.                                                     .set_title("提示")
  18.                                                     .set_description("文件夹中无图片文件!")
  19.                                                     .show();
  20.                                                 println!("文件夹为空");
  21.                                             }
  22.                                             
  23.                                         }
复制代码
注意到,我们获取了文件夹的路径后,使用folderbrowser函数进行了遍历:
  1. ///
  2. ///遍历文件夹
  3. ///
  4. pub fn folderbrowser(path:std::path::PathBuf) ->Result<Vec<std::path::PathBuf>,String> {
  5.         match std::fs::read_dir(path) {
  6.             Ok(dirs) => {
  7.                 let paths = dirs.filter_map(
  8.                     |dir| {
  9.                         dir.ok().map(|dir_dir| dir_dir.path())
  10.                                 .filter(|path| {
  11.                                     if let Some(ext) = path.extension() {
  12.                                         ext == "png" || ext == "jpg" || ext == "webp" || ext == "bmp" || ext == "jpeg"
  13.                                     } else {
  14.                                         false
  15.                                     }
  16.                                 })
  17.                     }
  18.                 ).collect();
  19.                 Ok(paths)
  20.             },
  21.             Err(e) =>{
  22.                 Err(format!("Error:{}",e))
  23.             }
  24.         }
  25. }
复制代码
如上,我们使用rust的标准库std的fs来处置惩罚文件路径,将文件夹中的每个图片路径都提取出来,而不符合图片后缀名的文件,则忽略。
3、样式实现


注意上述图片红色箭头所指,当前主图片对应的缩略图,其边框是与其他边框不一样的,假如是在前端项目中,实现这样的效果黑白常简单的,而在iced中,假如我们希望实现这样的效果,就必要为图片进行自定义样式的设置。
在iced中,image元素自己是没有样式设置的,因此,我们的处置惩罚办法是在image元素外面套一层container元素:
  1. container(
  2.                         image(image::Handle::from_path(self.imgs[i].display().to_string())).width(100).height(100)
  3.                         ).style(move |t| styles::mycontainerstyle_border(t,i.to_string(),self.current_index))
复制代码
针对于container元素,我们就可以设置其style参数,具体来说,对于缩略图的图片,我们为其添加了一层套壳,通过设置套壳的样式来展现区别。
我们新建一个styles.rs文件,在此中添加mycontainerstyle_border函数:
  1. pub fn mycontainerstyle_border(t:&Theme,s:String,index:usize) ->iced::widget::container::Style {
  2.    
  3.    if s == index.to_string() {
  4.         iced::widget::container::Style {
  5.             border:iced::Border{
  6.                 color:iced::color!(0x669EF1), //#669EF1FF
  7.                 width:3.0,
  8.                 radius:iced::border::Radius::default(),
  9.             },
  10.             ..Default::default()
  11.         }
  12.    } else {
  13.     iced::widget::container::Style {
  14.         border:iced::Border{
  15.             color:Color::BLACK,
  16.             width:1.0,
  17.             radius:iced::border::Radius::default(),
  18.         },
  19.         ..Default::default()
  20.     }
  21.    }
  22.    
  23. }
复制代码
注意看上面的代码,我们实现缩略图边框变化的方法是,通过比力当前主图片的索引与图片列表的索引,假如划一,则表现当前图片是主图片,则设置其边框为蓝色加粗,否则其边框为默认。
颠末验证,这个方法是简单有效的。
4、动态演示



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

滴水恩情

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表