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图标正常显示了。

相关推荐
时光追逐者9 小时前
一款免费、简单、高效的在线数据库设计工具
数据库·mysql·oracle·sql server
another heaven9 小时前
【软考 2026 最新版 NoSQL 数据库全分类】
数据库·nosql
满天星83035779 小时前
【MySQL】表的操作
linux·服务器·数据库·mysql
yashuk9 小时前
Ubuntu 系统下安装 Nginx
数据库·nginx·ubuntu
F1FJJ9 小时前
VS Code 里管理 PostgreSQL,有哪些选择?主流扩展横向对比
网络·数据库·postgresql·容器
Bdygsl9 小时前
MySQL(8)—— 事务
数据库·mysql
IvorySQL9 小时前
直播回顾| PostgreSQL 18.3 x IvorySQL 5.3:开启 AI 数据库新纪元
数据库·postgresql·开源
编程之升级打怪9 小时前
数据库的实时同步和异步同步
数据库
captain3769 小时前
MySQL增删改查
数据库·mysql
IvorySQL10 小时前
PostgreSQL 技术日报 (3月27日)|当 AI 开始自动创建数据库
数据库·postgresql·开源