前言
本专栏是关于iced库的部件的介绍,iced库是基于rust的GUI库,可以创建基于rust的窗口程序。
关于iced
iced是跨平台的GUI框架,基于rust语言,它的架构受到Elm的启发。
发文平台
稀土掘金
概述
本文是专栏的第三篇,主要介绍iced的选择列表部件:pick_list。
1、pick_list部件构建
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,
Theme: pick_list::Catalog + overlay::menu::Catalog,
Renderer: core::text::Renderer,
{
PickList::new(options, selected, on_selected)
}
实例创建pick_list使用PickList::new(options, selected, on_selected)
。
2、实际应用
需要先导入pick_list:
use iced::widget::{button, combo_box, text,pick_list,radio,checkbox};
我们可以这样添加一个pick_lick:
pick_list(
HeroName::ALL,
self.heroname_fav.clone(),
Message::HeroNameSelected,
)
如上,HeroName是options,self.heroname_fav是selected,Message::HeroNameSelected是on_selected。 以上对应参数需要提前创建:
#[derive(Debug, Clone)]
struct MyApp {
heroname_fav:Option<HeroName>,
heroname_select:String,
showimgpath:String,
}
#[derive(Debug, Clone)]
enum Message {
Null,
HeroNameSelected(HeroName),
}
其中,HeroName我们在另一个模块中定义:
use std::fmt::Display;
#[derive(Debug,Clone,PartialEq)]
pub enum HeroName{
Bingnv,
JianSheng,
QuanNeng,
ShuiRen,
XianZhi,
XiaoNiu,
XiaoXiao,
}
impl HeroName{
pub const ALL:&'static [HeroName] = &[
HeroName::Bingnv,
HeroName::JianSheng,
HeroName::QuanNeng,
HeroName::ShuiRen,
HeroName::XianZhi,
HeroName::XiaoNiu,
HeroName::XiaoXiao,
];
pub fn display(&self) -> String {
match self{
HeroName::Bingnv => "冰女".to_string(),
HeroName::JianSheng => "剑圣".to_string(),
HeroName::QuanNeng => "全能".to_string(),
HeroName::ShuiRen => "水人".to_string(),
HeroName::XianZhi => "先知".to_string(),
HeroName::XiaoNiu => "小牛".to_string(),
HeroName::XiaoXiao => "小小".to_string(),
}
}
pub fn getpath(&self)->String{
match self{
HeroName::Bingnv => "./public/冰女.jpg".to_string(),
HeroName::JianSheng => "./public/剑圣.jpg".to_string(),
HeroName::QuanNeng => "./public/全能.jpg".to_string(),
HeroName::ShuiRen => "./public/水人.jpg".to_string(),
HeroName::XianZhi => "./public/先知.jpg".to_string(),
HeroName::XiaoNiu => "./public/小牛.jpg".to_string(),
HeroName::XiaoXiao => "./public/小小.jpg".to_string(),
}
}
}
impl Display for HeroName{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self{
HeroName::Bingnv => write!(f, "冰女"),
HeroName::JianSheng => write!(f, "剑圣"),
HeroName::QuanNeng => write!(f, "全能"),
HeroName::ShuiRen => write!(f, "水人"),
HeroName::XianZhi => write!(f, "先知"),
HeroName::XiaoNiu => write!(f, "小牛"),
HeroName::XiaoXiao => write!(f, "小小"),
}
}
}
来看下最终UI效果:
我们在本例中实现这样的功能,根据选择的英雄不同,在底下显示不同的英雄图像,英雄图形我们提前下载好,放到public文件夹下:
pub fn getpath(&self)->String{
match self{
HeroName::Bingnv => "./public/冰女.jpg".to_string(),
HeroName::JianSheng => "./public/剑圣.jpg".to_string(),
HeroName::QuanNeng => "./public/全能.jpg".to_string(),
HeroName::ShuiRen => "./public/水人.jpg".to_string(),
HeroName::XianZhi => "./public/先知.jpg".to_string(),
HeroName::XiaoNiu => "./public/小牛.jpg".to_string(),
HeroName::XiaoXiao => "./public/小小.jpg".to_string(),
}
}
我们为HeroName定义了一个根据选项返回图片路径的函数,然后直接调用此函数即可:
Message::HeroNameSelected(heroname)=>{
self.heroname_fav = Some(heroname.clone());
self.heroname_select = heroname.display();
self.showimgpath = heroname.getpath();
}
我们来看一下实际演示:
3、pick_list部件自定义样式
pick_list与combo_box有点像,样式也分为两项,一项是选择器,一项是menu。其源码中关于样式的定义:
/// Sets the style of the [`PickList`].
#[must_use]
pub fn style(mut self, style: impl Fn(&Theme, Status) -> Style + 'a) -> Self
where
<Theme as Catalog>::Class<'a>: From<StyleFn<'a, Theme>>,
{
self.class = (Box::new(style) as StyleFn<'a, Theme>).into();
self
}
/// Sets the style of the [`Menu`].
#[must_use]
pub fn menu_style(
mut self,
style: impl Fn(&Theme) -> menu::Style + 'a,
) -> Self
where
<Theme as menu::Catalog>::Class<'a>: From<menu::StyleFn<'a, Theme>>,
{
self.menu_class = (Box::new(style) as menu::StyleFn<'a, Theme>).into();
self
}
我们创建一个自定义结构体:MyPickListStyle,然后为其添加函数如下:
struct MyPickListStyle;
impl MyPickListStyle {
fn pickliststyle(t:&iced::Theme,s:iced::widget::pick_list::Status) -> iced::widget::pick_list::Style{
match s {
iced::widget::pick_list::Status::Active =>{
iced::widget::pick_list::Style {
text_color:color!(0x504D4D), //#ECCE73FF
placeholder_color:color!(0x504D4D),
handle_color:color!(0x504D4D),
background:iced::Background::Color(color!(0xECCE73)),
border:iced::Border {
color:color!(0x504D4D),
width:1.0,
radius:{1.0;4}.into(),
},
}
}
iced::widget::pick_list::Status::Hovered =>{
iced::widget::pick_list::Style {
text_color:color!(0x504D4D), //#504D4DFF
placeholder_color:color!(0x504D4D),
handle_color:color!(0x504D4D),
background:iced::Background::Color(color!(0xECCE73)),
border:iced::Border {
color:color!(0x504D4D),
width:1.0,
radius:{1.0;4}.into(),
},
}
}
iced::widget::pick_list::Status::Opened =>{
iced::widget::pick_list::Style {
text_color:color!(0x504D4D), //#504D4DFF
placeholder_color:color!(0x504D4D),
handle_color:color!(0x504D4D),
background:iced::Background::Color(color!(0xECCE73)),
border:iced::Border {
color:color!(0x504D4D),
width:1.0,
radius:{1.0;4}.into(),
},
}
}
}
}
fn menustyle(t:&iced::Theme) -> iced::widget::overlay::menu::Style{
iced::widget::overlay::menu::Style {
background:iced::Background::Color(color!(0xECCE73)),
text_color:color!(0x504D4D),
border:iced::Border {
color:color!(0x504D4D),
width:1.0,
radius:{1.0;4}.into(),
},
selected_text_color:color!(0x504D4D),
selected_background:iced::Background::Color(color!(0x60C6F2)), //#60C6F2FF
}
}
}
然后我们来调用样式,如下:
pick_list(
HeroName::ALL,
self.heroname_fav.clone(),
Message::HeroNameSelected,
).style(|t,s|MyPickListStyle::pickliststyle(t, s))
.menu_style(|t|MyPickListStyle::menustyle(t))
看一下效果演示: