Rust UI开发(二):iced中如何为窗口添加icon图标

注:此文适合于对rust有一些了解的朋友

iced是一个跨平台的GUI库,用于为rust语言程序构建UI界面。

想要了解如何构建简单窗口的可以看本系列的第一篇:
Rust UI开发:使用iced构建UI时,如何在界面显示中文字符

本篇是系列第二篇,主要解决一个问题,就是为窗口添加图标icon。

注:窗口图标在其他语言中,应该是非常容易实现的,但iced是一个发展中的库,很多方面还不成熟,我在用iced自己的方法测试window图标,花了很多时间,效果还不好,所以特意记录此篇,一来做个记录,方便以后回看,二来给其他有这方面问题的朋友做个参考。

我们先来看一下iced中对于窗口参数设置里icon的定义:

rust 复制代码
/// The icon of the window. 
    pub icon: Option<Icon>,

icon参数是一个枚举,枚举类型是Icon。

再去看Icon的定义:

rust 复制代码
/// An window icon normally used for the titlebar or taskbar.
#[derive(Debug, Clone)]
pub struct Icon {
    rgba: Vec<u8>,
    size: Size<u32>,
}

可以看到,这里Icon的数据是rgba数据,是一种图像的数据类型。

rgba是rgb的基础上,另外增加了一个a(阿尔法)通道,表示透明度信息。

也就是说,rgb是u8,u8,u8,而rgba是u8,u8,u8,u8。这里u8指2的8次方即256种颜色值(0-255)。

总的来说,你只要知道在这里,Icon是{rgba,size}组合的数据形式。

所以,如果我们要设置这个icon图标,我们知道,图片应该是rgba格式的,且设置一个尺寸如4848,6464,类似这种。

先看图像的格式,通常如果读取一张图片,数据应该是rgb,所以需要转换。

看下面的代码:

rust 复制代码
let img_byte=include_bytes!("img3.jpg");       
    //println!("this is:{:?}",img_byte);
    let ico=icon::from_rgba(img_byte.to_owned().into(), 32, 29);
    let ico_file=match ico{
        Ok(file)=>file,
        Err(error)=>panic!("error is {}",error),
    };

这段代码,是利用include_bytes方法,将图像的像素转为一个字节数组。

然后调用iced::window::icon的from_rgba函数,这个函数就是构建一个Icon对象,以rgba的形式,从其他色彩类型转化。

他返回的是一个Result数据,所以需要进行错误处理,然后利用Some(ico_file)返回枚举类型的数据格式,即:

Option。

rust 复制代码
icon:Some(ico_file) 

这个方法是可行的,我在测试中可以正常启动窗口并显示图片,但是有些问题,首先就是对图片有要求,在测试中遇到两个问题:

一是图片包含像素长度不对,编译器提示无法被4整除,也就是不能分成rgba四个通道,所以会报错。

二是加入图片像素长度可以了,但你的尺寸size设置有问题,举例说明,图片像素字节加起来是120个,除以4就是30,但你的尺寸设置为3232,这就不行,如果把尺寸修改为56,就可以了。

关于上面这个方法,首先它是能够实现在窗口上加载图标的,但是目前我还没有搞清楚图片的像素数据就要是怎么匹配的,导致我在测试中发现,虽然能显示图片,但图片显然和原始图片的图案对不上,也就是像素可能错位了。

第二个方法

所以,我建议使用第二个方法,第二个方法是使用第三方库来处理图片,得到一个完整的rgba图片数据。

这里会用到image库,github地址:

https://github.com/image-rs/image/tree/master

要使用这个库,需要在cargo.toml文件里添加依赖:

rust 复制代码
image="*"
num-complex="*"

也可以指定版本号。

然后导入:

rust 复制代码
extern  crate image;
extern crate num_complex;

来看代码:

rust 复制代码
  //第二种获取rgba图片的方法,利用Image库
    let img2=image::open("../iced_test/src/img3.jpg");    
    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),
    };

这里有个注意的地方,就是image库的open函数,打开图像文件,其参数是图片的路径,但是必须是:

".../iced_test/src/img3.jpg"

这种形式,如果你写成:

".iced_test/src/img3.jpg" 或者 "img3.jpg"

image好像会识别错误,它识别的相对路径,必须在前面加上:

.../

image::open函数返回的是一个Result数据:

Result<DynamicImage, ImageError>

我们利用match返回DynamicImage数据,这个DynamicImage是image的一个枚举数据,它拥有转换的功能,我们使用to_rgba8()函数,返回一个rgbaImage数据,rgbaIMage包含:

ImageBuffer<Rgba, Vec>

得到ImageBuffer,可以看到里面包含rgba,我们使用:

to_vec()转为适合的格式,这样ico2就得到想要的rgba格式的Icon了,但ico2还是一个result。我们用match取出Icon即可。

rust 复制代码
let ico2=icon::from_rgba(img2_file.to_vec(), 64, 64); 
rust 复制代码
let ico2_file=match ico2{  
        Ok(file)=>file,
        Err(error)=>panic!("error is {}",error),
    };

然后window的Settings中:

rust 复制代码
 icon:Some(ico2_file)

这样就可以了,看一下实际窗口效果:

图标图片:

实际窗口:

可以看到,窗口的icon图标正常显示了。

相关推荐
梦想平凡3 分钟前
情怀棋牌源代码焕新记录(一):全新国风UI与原版工程梳理
java·服务器·数据库·websocket·网络协议·cocos2d
cspttty5 分钟前
FP&A应届岗技能路线:Excel建模、SQL取数、BI看板与预算分析
大数据·数据库
微学AI24 分钟前
飞牛 NAS 部署 prompts.chat:自建提示词库、导入社区内容,再配置固定公网访问
数据库·内网穿透
羑悻的小杀马特26 分钟前
从写 YAML 到集群自愈:KES-Operator 把 KES 集群接进 Kubernetes 原生体系
运维·数据库·容器·kubernetes
bksczm30 分钟前
MySQL基础篇之事务
linux·数据库·sql·mysql
李白客31 分钟前
数据库管理工具怎么选?Navicat、DataGrip、DBeaver 六维横向对比与选型建议
运维·数据库
马立杰32 分钟前
mysql中Illegal mix of collations for operation “UNION”错误的解决方法
数据库·sql·网络安全
蓝速科技34 分钟前
蓝速 K10 三防平板在工业恶劣工况下的选型与应用指南
大数据·运维·数据库·人工智能·科技
bksczm35 分钟前
MySQL基础篇之视图与用户管理
linux·数据库·sql·mysql
香菜TTT42 分钟前
怎么实现MySQL的主从同步机制
数据库·mysql