RustGUI学习(iced)之小部件(三):如何使用下拉列表pick_list?

前言
本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。
iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1.

概述
这是本专栏的第三篇,主要讲述下拉列表pick_list部件的使用,会结合实例来说明。
系列博文链接
1、RustGUI学习(iced)之小部件(一):如何使用按钮和文本标签部件
2、RustGUI学习(iced)之小部件(二):如何使用滑动条部件

环境配置:
系统:windows
平台:visual studio code
语言:rust
库:iced

在这里插入图片描述
注:iced是一个受Elm启发而编写,适用于rust语言的跨平台的GUI库。

本篇内容:
1、pick_list

下拉列表部件

pick_list部件在iced中的定义如下:

/// Creates a new [`PickList`].     
///
/// [`PickList`]: crate::PickList
pub fn pick_list<'a, T, L, V, Message, Theme, Renderer>(
    options: L,
    selected: Option<V>,
    on_selected: impl Fn(T) -> Message + 'a,
) -> PickList<'a, T, L, V, Message, Theme, Renderer>
where
    T: ToString + PartialEq + Clone + 'a,
    L: Borrow<[T]> + 'a,
    V: Borrow<T> + 'a,
    Message: Clone,
    Renderer: core::text::Renderer,
    Theme: pick_list::StyleSheet
        + scrollable::StyleSheet
        + overlay::menu::StyleSheet
        + container::StyleSheet,
    <Theme as overlay::menu::StyleSheet>::Style:
        From<<Theme as pick_list::StyleSheet>::Style>,
{
    PickList::new(options, selected, on_selected)
}

其由PickList来创建:

/// A widget for selecting a single value from a list of options.              
#[allow(missing_debug_implementations)]
pub struct PickList<
    'a,
    T,
    L,
    V,
    Message,
    Theme = crate::Theme,
    Renderer = crate::Renderer,
> where
    T: ToString + PartialEq + Clone,
    L: Borrow<[T]> + 'a,
    V: Borrow<T> + 'a,
    Theme: StyleSheet,
    Renderer: text::Renderer,
{
    on_select: Box<dyn Fn(T) -> Message + 'a>,
    on_open: Option<Message>,
    on_close: Option<Message>,
    options: L,
    placeholder: Option<String>,
    selected: Option<V>,
    width: Length,
    padding: Padding,
    text_size: Option<Pixels>,
    text_line_height: text::LineHeight,
    text_shaping: text::Shaping,
    font: Option<Renderer::Font>,
    handle: Handle<Renderer::Font>,
    style: Theme::Style,
}

我们来看以下pick_list涉及的参数或属性,首先是on_select,从其定义可知这是一个动态指针,在实际使用时,on_select表示当选择下拉列表时,会触发这个事件,其反馈当前选择的项。
然后是on_open和on_close两个属性,分别表示下拉列表在打开和关闭时返回的消息,因为通常来说,下拉列表并不太关注打开和关闭时的状态,所以此参数可以不设置,使用默认即可。
然后是options参数,顾名思义,此参数即是下拉列表部件的下拉选项,从其定义来说,是一个借用类型且具有相同的生命周期(与借用的数组一致)。在实际使用来说,此处应该是一个枚举数组。
placeholder参数比较简单,是一个枚举字符,实际表示下拉列表没有选项时显示的一个提示文字。如下:
在这里插入图片描述
接下来是selected,其定义也是枚举类型,但枚举的参数是借用类型,且具有借用数组一样的生命周期。此参数是实时显示选择的下拉项。需要在update函数里更新,否则下拉列表选择后并不会更新UI。
width、padding、text_size、text_line_height、text_shaping、font这些都是一些基本参数,比较简单,主要设置一些尺寸或者文字。
handle是下拉列表右侧的箭头的属性,默认是箭头,可以修改为其他预设,如:
在这里插入图片描述
修改了箭头的尺寸,显示如上,可以看到和默认的有明显区别。除了箭头外,还可以使用自定义侧icon来替换,只不过需要自行设计。如下:
在这里插入图片描述
使用字符作为handle,但通常来说,下拉列表常见的都是箭头。
再来看最后一个属性,style,和之前的部件一样,style用于设计下拉列表部件的外观,其在iced中的定义如下:

/// A set of rules that dictate the style of a container.  
pub trait StyleSheet {
    /// The supported style of the [`StyleSheet`].
    type Style: Default + Clone;

    /// Produces the active [`Appearance`] of a pick list.
    fn active(&self, style: &<Self as StyleSheet>::Style) -> Appearance;

    /// Produces the hovered [`Appearance`] of a pick list.
    fn hovered(&self, style: &<Self as StyleSheet>::Style) -> Appearance;
}

其中,Appearance定义如下:

/// The appearance of a pick list.       
#[derive(Debug, Clone, Copy)]
pub struct Appearance {
    /// The text [`Color`] of the pick list.
    pub text_color: Color,
    /// The placeholder [`Color`] of the pick list.
    pub placeholder_color: Color,
    /// The handle [`Color`] of the pick list.
    pub handle_color: Color,
    /// The [`Background`] of the pick list.
    pub background: Background,
    /// The [`Border`] of the pick list.
    pub border: Border,
}

可以看到,pick_list部件的Appearance有五个可设置的属性,其中,text_color是文字颜色,placeholder_color是空闲时的文字颜色,handle_color顾名思义是右侧箭头的颜色,background指背景设置,而border是边框设置。
下面我们设置一下自定义pick_list,首先新建一个pick_list的外观结构体:

struct MyPickListStyle;

然后对结构体实现StyleSheet:

impl pick_list::StyleSheet for MyPickListStyle {    
    type Style = Theme;
    //激活时外观
    fn active(&self, style: &Self::Style) -> pick_list::Appearance {
        pick_list::Appearance {
            text_color:Color::from_rgb8(142, 204, 240),
            placeholder_color:Color::BLACK,
            handle_color:Color::from_rgb8(18, 27, 155),
            background:Background::Color(Color::from_rgb8(215, 217, 249)),
            border:Border{color:Color::BLACK,width:1.0,radius:[3.0;4].into()},
    }
}
    fn hovered(&self, style: &Self::Style) -> pick_list::Appearance {
        pick_list::Appearance {
            text_color:Color::from_rgb8(76, 87, 240),
            placeholder_color:Color::BLACK,
            handle_color:Color::from_rgb8(18, 27, 155),
            background:Background::Color(Color::from_rgb8(215, 217, 249)),
            border:Border { color: Color::BLACK, width: 1.0, radius: [3.0;4].into() },
    }
    }
}

需要注意的是,pick_list的动态样式有些特别,看一下官方定义:

/// The style of a pick list. 
#[derive(Clone, Default)]
pub enum PickList {
    /// The default style.
    #[default]
    Default,
    /// A custom style.
    Custom(
        Rc<dyn pick_list::StyleSheet<Style = Theme>>,
        Rc<dyn menu::StyleSheet<Style = Theme>>,
    ),
}

可以看到,其Custom选项有2个参数,除了pick_list样式外,还要求了menu样式,虽然不明白作者为什么这么设置,但如果要实现pick_list的自定义样式,我们必须为其添加第二个参数即menu部件的动态样式,所以我们还需要新建menu样式结构体:

struct MyMenuStyle;

然后设置StyleSheet:

impl menu::StyleSheet for MyMenuStyle {   
    type Style = Theme;
    fn appearance(&self, style: &Self::Style) -> menu::Appearance {
        menu::Appearance{
            text_color:Color::BLACK,
            background:Background::Color(Color::from_rgb8(215, 217, 249)),
            border:Border { color: Color::BLACK, width: 1.0, radius: [3.0;4].into() },
            selected_text_color:Color::BLACK,
            selected_background:Background::Color(Color::from_rgb8(180, 184, 248)),
        }
    }
}

当自定义样式设置好后,就可以调用了:

let style9=theme::PickList::Custom(Rc::new(MyPickListStyle),Rc::new(MyMenuStyle));  

然后设置pick_list的style属性即可,我们来看一下实际效果:
active:
在这里插入图片描述
hovered:
在这里插入图片描述
可以看到,自定义样式还是非常明显的不同的。

好了,关于属性的设置就说到这,接下来说一下options、selected、on_select这三个选项在实际中如何设置:
先来看一下三个参数的定义:

options: L,

其中,L为:

L: Borrow<[T]> + 'a, 

T:

T: ToString + PartialEq + Clone,

此处,T是泛型,官方定义加了约束,T是可以复制且能转为字符并且可比较的类型。而L是T的借用,且生命周期一致。

selected: Option<V>,

selected是枚举,枚举的类型是V:

V: Borrow<T> + 'a,

与options不同的是,V借用T,而L借用的是数组[T].

on_select: Box<dyn Fn(T) -> Message + 'a>, 

on_select是和事件绑定的,是消息的触发,它被定义为一个指针,指向的是pick_list的选项,并接收反馈的消息内容。综合起来,Box<dyn Fn(T) -> Message + 'a> 表示一个指向实现了Fn(T) -> Message trait的对象的堆上分配的智能指针,且这个对象的生命周期至少为’a。
以上是关于官方定义的解释,下面我们来看一下实际应用。

pick_list(&Item::ALL[..],self.selected_item,Message::ItemSelected)           

此处,&Item::ALL[…]对应的是options,selected对应的是self.selected_item,而on_select对应的是Message::ItemSelected。
分别来看一下各个变量是如何创建的。

先创建了枚举Item,此处为其添加了Default特性。

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]  
enum Item{
    #[default]
    Rust,
    Elm,
    Ruby,
    Haskell,
    C,
    JS,
    Other,

}

然后,Item作为pick_list的选项的数据,其必须符合定义时泛型T的定义:

T: ToString + PartialEq + Clone, 

T可以转为字符,所以,我们需要为Item实现Display特性:

impl std::fmt::Display for Item{      
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f,"{}",match self{
            Item::Rust => "Rust",
            Item::Elm => "Elm",
            Item::Ruby => "Ruby",
            Item::Haskell => "Haskell",
            Item::C => "C",
            Item::JS => "Javascript",
            Item::Other => "Other",
        })
    }
}

Display可以很方便的设置参数转为字符的格式化设置。
而为了使Item的选项能够作为数组[T]传入options,需要将Item实现数组定义:

impl Item{    
    const ALL:[Item;7]=[
        Item::Rust,
        Item::Elm,
        Item::Ruby,
        Item::Haskell,
        Item::C,
        Item::JS,
        Item::Other,
    ];
}

此处定义了一个常量ALL,ALL包含了Item的所有项,且是数组。
而selected的参数selected_item 则定义在结构体中:

struct Example{ 
    value:i64,
    value_sld:f32,
    value_sld2:f32,
    default:f32,
    step:f32,
    shift_step:f32,
    selected_item:Option<Item>,
}

注意selected_item的类型是枚举。
而on_select的参数则是消息:

#[derive(Debug,Clone,Copy)]
enum Message{
    Clicked,
    SliderChanged(f32),
    ItemSelected(Item),
}

这样一来,Item中定义的项,将会按照Display设置的显示格式,显示在下拉列表中:
在这里插入图片描述
当我们选择其中一项时,会触发on_select,此时,选中的项的内容将作为消息传递给Message::ItemSelected(Item),其中item就是选中项。
我们只需要在update函数中处理消息即可:

  fn update(&mut self,message:Message){      
        match message{
            Message::Clicked => {
                self.value +=1;
            }    
            Message::SliderChanged(value)=>{
                self.value_sld=value;
            }
            Message::ItemSelected(item)=>{
                self.selected_item=Some(item);
                println!("{:?}",item);
            }
        }

    }

可以看到,我们将选中项作为值赋给了变量selected_item,也就是只要我们选择任何项,selected_item都会跟随改变,也就是下拉列表选择完成后显示的就是我们选择的项。
我们也可以将selected_item 赋予其他部件,如text,这样我们选择什么项,就可以在UI上显示出来:
在这里插入图片描述  
综上,我们已经基本了解了pick_list作为小部件是如何定义和使用的,其属性和参数又是如何设置的。
下面看一下动态演示:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/583340.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年,新手做抖音小店想要赚钱,必须明白三件事!

大家好&#xff0c;我是电商糖果 有不少小店的商家都说过&#xff0c;现在的抖音小店比三四年前复杂了。 三四年前抖音小店刚刚出现&#xff0c;平台规则还没有那么多&#xff0c;很多机制也不太成熟。 那个时期的抖店说是捡钱的&#xff0c;一点儿都不假。 但是如果说你现…

Linux详解:进程等待

文章目录 进程等待等待的必要性进程等待的方法waitwaitpid获取子进程status阻塞等待 与 非阻塞等待 进程等待 等待的必要性 子进程退出&#xff0c;父进程不进行回收的话&#xff0c;就可能造成僵尸进程&#xff0c;进而造成内存泄露 如果进程进入了僵尸状态&#xff0c;kill…

机器学习:驱动现代交通运输革命的AI智慧引擎

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

玄子Share-引导过程与服务控制

玄子Share-引导过程与服务控制 Linux操作系统引导过程 系统初始化进程 init 进程 由 Linux 内核加载运行 /sbin/init 程序init 进程是系统中第一个进程init 进程的 PID&#xff08;进程标记&#xff09;号永远为 1 Systemd Systemd是Linux操作系统的一种init软件CentOS7中采用…

【Linux开发 第十二篇】搭建JavaEE环境

搭建开发环境 搭建javaEE环境 搭建javaEE环境 在Linux下开发JavaEE需要安装软件包&#xff1a; 安装jdk 安装步骤&#xff1a; 在opt目录下创建jdk目录通过xftp上床到jdk目录中进入到jdk目录中&#xff0c;解压jdk压缩包在/usr/local下创建java目录将解压完成的jdk文件移动…

SpringBoot框架学习笔记(一):依赖管理和自动配置

本文为个人笔记&#xff0c;仅供学习参考之用&#xff0c;如有不当之处请指出。 本文基于springboot2.5.3版本&#xff0c;开发环境需要是 jdk 8 或以上&#xff0c;maven 在 3.5 1 SpringBoot 基本介绍 1.1 官方文档 &#xff08;1&#xff09; 官网 : https://spring.io/pr…

张朝阳对话华为Fellow陈海波:万物智联时代,鸿蒙如何实现“换道超车”?

随着智能终端设备的普及和万物智联时代的加速到来&#xff0c;鸿蒙生态的高速发展正引发全行业的关注。 搜狐创始人、董事局主席兼CEO、物理学博士张朝阳与华为Fellow、基础软件首席科学家陈海波带来了一场关于鸿蒙生态的公开课。鸿蒙技术架构有哪些领先性?HarmonyOS发布5年来…

compose调用系统分享功能分享图片文件

compose调用系统分享功能图片文件 简介UI界面提供给外部程序的文件访问权限创建FileProvider设置共享文件夹 通用分享工具虚拟机验证结果参考 本系列用于新人安卓基础入门学习笔记&#xff0c;有任何不同的见解欢迎留言 运行环境 jdk17 andriod 34 compose material3 简介 本案…

Hadoop3:集群搭建及常用命令与shell脚本整理(入门篇,从零开始搭建)

一、集群环境说明 1、用VMware安装3台Centos7.9虚拟机 2、虚拟机配置&#xff1a;2C&#xff0c;2G内存&#xff0c;50G存储 3、集群架构 从表格中&#xff0c;可以看出&#xff0c;Hadoop集群&#xff0c;主要有2部分&#xff0c;一个是HDFS服务&#xff0c;一个是YARN服务 …

[系统安全] 六十.威胁狩猎 (1)APT攻击检测及防御与常见APT组织的攻击案例分析

您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列。因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全、逆向分析和恶意代码检测,“系统安全”系列文章会更加聚焦,更加系…

四、管道与重定向

四、管道与重定向 1 重定向 0,标准输入(键盘) 1,标准输出 2,标准错误&#xff0c; 3,进程在执行过程中打开的其他文件。 &:表示正确错误混合输出1.1 输出重定向 (覆盖&#xff0c;追加) > ----覆盖 >> ----追加 正确输出&#xff1a; 1> 1>> 等价…

Git 仓库内容操作

Git 仓库内容操作 | CoderMast编程桅杆Git 仓库内容操作 添加文件到暂存区 使用如下指令将工作区的文件添加到暂存区&#xff0c;告诉 Git 在下次 commit 时哪些文件做出了修改。 commit 指令详看后续 添加一个或多个文件到暂存区&#xff1a; 添加指定目录到暂存区 添加当前目…

ffmpeg与sdl的个人笔记

说明 这里的ffmpeg基础知识和sdl基础知识仅提及与示例代码相关的知识点, 进阶可学习雷神的博客。 https://blog.csdn.net/leixiaohua1020 当然&#xff0c;如代码写的有问题或有更好的见解&#xff0c;欢迎指正&#xff01; 音视频基础知识 在学习音视频理论知识时&#xff…

CSS中设置透明度的2个属性:opacity,RGBA以及它们的区别

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端工具”&#xff0c;可获取 Web 开发工具合…

试用了三个Ai音乐工具,我的偶像河图要完蛋了

试了三个生成音乐的ai工具&#xff0c;分别是爆火的suno,后期新秀udio&#xff0c;还有我们国内的天工。 先说感受&#xff0c;suno和天工我觉得稍微靠前&#xff0c;udio可能我的配置风格有问题&#xff0c;啪啪啪连选了好几个风格&#xff0c;生成的东西有点怪。 我随手写了…

【机器学习基础1】什么是机器学习、预测模型解决问题的步骤、机器学习的Python生态圈

文章目录 一. 什么是机器学习1. 概念2. 机器学习算法分类 二. 利用预测模型解决问题的步骤三. 机器学习的Python生态圈 一. 什么是机器学习 1. 概念 机器学习&#xff08;Machine Learning&#xff0c;ML&#xff09;是一门多领域的交叉学科&#xff0c;涉及概率论、统计学、…

深度学习 --- stanford cs231学习笔记(一)

stanford cs231学习笔记(一) 1&#xff0c;先是讲到了机器学习中的kNN算法&#xff0c;然后因为kNN分类器的一些弊端&#xff0c;引入了线性分类器。 kNN算法的三大弊端&#xff1a; (1)&#xff0c;计算量大&#xff0c;当特征比较多时表示性差 (2)&#xff0c;训练时耗时少…

01 - 安装Kettle

下载安装包 我这边提供的安装包是绿色版的&#xff0c;开箱即用 Kettle.exe 阿里云盘分享 提取码: 8sd5 点击链接保存&#xff0c;或者复制本段内容&#xff0c;打开「阿里云盘」APP &#xff0c;无需下载极速在线查看&#xff0c;视频原画倍速播放。 启动步骤 解压 双击Spo…

注意力机制(四)(多头注意力机制)

​&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;《深度学习基础知识》 相关专栏&#xff1a; ⚽《机器学习基础知识》 &#x1f3d0;《机器学习项目实战》 &#x1f94e;《深度学习项目实…

Python | Leetcode Python题解之第55题跳跃游戏

题目&#xff1a; 题解&#xff1a; class Solution:def canJump(self, nums: List[int]) -> bool:n, rightmost len(nums), 0for i in range(n):if i < rightmost:rightmost max(rightmost, i nums[i])if rightmost > n - 1:return Truereturn False