前言
本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。
iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1.
概述
这是本专栏的第二篇,主要讲述滑动条(slider)这个部件的使用,会结合实例来说明。
系列博客链接:
1、RustGUI学习(iced)之小部件(一):如何使用按钮和文本标签部件
环境配置:
系统:windows
平台:visual studio code
语言:rust
库:iced
注:iced是一个受Elm启发而编写,适用于rust语言的跨平台的GUI库。
本篇内容:
1、slider
滑动条部件
slider部件在iced中的定义如下:
/// Creates a new [`Slider`].
///
/// [`Slider`]: crate::Slider
pub fn slider<'a, T, Message, Theme>(
range: std::ops::RangeInclusive<T>,
value: T,
on_change: impl Fn(T) -> Message + 'a,
) -> Slider<'a, T, Message, Theme>
where
T: Copy + From<u8> + std::cmp::PartialOrd,
Message: Clone,
Theme: slider::StyleSheet,
{
Slider::new(range, value, on_change)
}
其由Slider来创建:
#[allow(missing_debug_implementations)]
pub struct Slider<'a, T, Message, Theme = crate::Theme>
where
Theme: StyleSheet,
{
range: RangeInclusive<T>,
step: T,
shift_step: Option<T>,
value: T,
default: Option<T>,
on_change: Box<dyn Fn(T) -> Message + 'a>,
on_release: Option<Message>,
width: Length,
height: f32,
style: Theme::Style,
}
从上面可以看到,slider包含有以上属性或者方法,我们一一来看一下。
range表示的是滑动条的范围,即最小和最大值。
step表示滑动条滑动的最小单位,即拖动时slider值改变的最小值。
shift_step表示当按下shift键时拖动滑动条的最小值。
value表示滑动条当前值。
defualt表示默认值,或者初始值。
on_change表示滑动条滑动时触发。
on_release表示滑动条释放时触发。
width、height表示宽、高。
style表示滑动条的样式,有默认和自定义可选。
我们先来看一下slider实际应用:
slider(1.0..=40.0, self.value_sld,Message::SliderChanged).default(self.default)
.step(self.step).shift_step(self.shift_step)
.width(100).style(style8),
如上代码,range为1.0…=40.0,这种表示方式,表示最小为1,最大为40.需要注意的是数据格式,range、value包括step等都需要保持一致,如此处是f32.
此处的value为self.value_sld,来自于自定义的struct:
struct Example{
value:i64,
value_sld:f32,
default:f32,
step:f32,
shift_step:f32,
}
on_change则绑定了enum的message:
#[derive(Debug,Clone,Copy)]
enum Message{
Clicked,
SliderChanged(f32),
}
即每当滑动条滑动时,都会将当前滑动条的值传入SliderChanged(f32)中,我们只需要在iced的update函数中去处理这个值即可。
Message::SliderChanged(value)=>{
self.value_sld=value;
}
将滑动条的内部值传递给value_sld,value_sld表示滑块的实时位置,这样,拖动时,滑块就可以跟踪鼠标实时滑动。
default、step和shift_step只需要将前面定义好的值填入即可:
struct Example{
value:i64,
value_sld:f32,
value_sld2:f32,
default:f32,
step:f32,
shift_step:f32,
}
width用于设置滑动条的宽度,可以使用预设,也可以自定义值,无需多说。
主要说一下style,即滑动条的样式设置。前面说过,style有默认和自定义两种可选,先来看一下默认样式:
let style8=theme::Slider::Default;
看一下实际效果:
默认样式看起来也不错,如果不满足于默认样式,那么可以使用自定义,和我们在前一篇中说到的按钮的样式自定义一样,如果要对slider进行自定义,也需要对其实现StyleSheet这个特性,只不过按钮时button style,而此处是slider style。
我们来看下slider的StyleSheet:
/// A set of rules that dictate the style of a slider.
pub trait StyleSheet {
/// The supported style of the [`StyleSheet`].
type Style: Default;
/// Produces the style of an active slider.
fn active(&self, style: &Self::Style) -> Appearance;
/// Produces the style of an hovered slider.
fn hovered(&self, style: &Self::Style) -> Appearance;
/// Produces the style of a slider that is being dragged.
fn dragging(&self, style: &Self::Style) -> Appearance;
}
和按钮的样式差不多,有一些区别在于其触发事件,slider没有press,而是dragging,即拖拽。
再来看下slider的外观Appearance:
/// The appearance of a slider.
#[derive(Debug, Clone, Copy)]
pub struct Appearance {
/// The colors of the rail of the slider.
pub rail: Rail,
/// The appearance of the [`Handle`] of the slider.
pub handle: Handle,
}
可以看到,slider的外观属性分为两方面,一个是rail,一个是handle,即滑动轨道和滑动块,可以分别设置。
其中:rail:
/// The appearance of a slider rail
#[derive(Debug, Clone, Copy)]
pub struct Rail {
/// The colors of the rail of the slider.
pub colors: (Color, Color),
/// The width of the stroke of a slider rail.
pub width: f32,
/// The border radius of the corners of the rail.
pub border_radius: border::Radius,
}
对于rail即滑动轨道,可以设置其前景色、背景色,轨道粗细以及轨道圆角。
handle:
/// The appearance of the handle of a slider.
#[derive(Debug, Clone, Copy)]
pub struct Handle {
/// The shape of the handle.
pub shape: HandleShape,
/// The [`Color`] of the handle.
pub color: Color,
/// The border width of the handle.
pub border_width: f32,
/// The border [`Color`] of the handle.
pub border_color: Color,
}
对于handle即滑块,可以设置滑块形状、颜色、边框粗细以及颜色,这其中滑块形状又可以设置:
/// The shape of the handle of a slider.
#[derive(Debug, Clone, Copy)]
pub enum HandleShape {
/// A circular handle.
Circle {
/// The radius of the circle.
radius: f32,
},
/// A rectangular shape.
Rectangle {
/// The width of the rectangle.
width: u16,
/// The border radius of the corners of the rectangle.
border_radius: border::Radius,
},
}
可以选择圆形,也可以选择方形。
综上所述,滑动条的外观可调整性还是很强的,无论是形状、颜色、大小以及圆角半径都可以自定义。
接下来我们看下如何自定义滑动条的样式:
1、新建样式结构体
//自定义slider样式1
struct MySliderStyle;
2、实现StyleSheet
impl slider::StyleSheet for MySliderStyle {
type Style = Theme;
//激活时外观
fn active(&self, style: &Self::Style) -> slider::Appearance {
slider::Appearance {
rail: Rail{
colors:(Color::from_rgb8(20, 48, 210),Color::from_rgb8(151, 155, 175)),
width:5.0,
border_radius:[3.0;4].into(),
},
handle: slider::Handle{
shape:HandleShape::Rectangle { width: 8, border_radius: [2.0;4].into() },
color:Color::from_rgb8(13, 248,44),
border_width:1.0,
border_color:Color::BLACK,
}
}
}
//悬停时外观
fn hovered(&self, style: &Self::Style) -> slider::Appearance {
slider::Appearance {
rail: Rail{
colors:(Color::from_rgb8(20, 48, 210),Color::from_rgb8(151, 155, 175)),
width:5.0,
border_radius:[3.0;4].into(),
},
handle: slider::Handle{
shape:HandleShape::Rectangle { width: 8, border_radius: [2.0;4].into()},
color:Color::from_rgb8(176, 171,186),
border_width:1.0,
border_color:Color::BLACK,
}
}
}
//拖拽时外观
fn dragging(&self, style: &Self::Style) -> slider::Appearance {
slider::Appearance {
rail: Rail{
colors:(Color::from_rgb8(20, 48, 210),Color::from_rgb8(151, 155, 175)),
width:5.0,
border_radius:[3.0;4].into(),
},
handle: slider::Handle{
shape:HandleShape::Rectangle { width: 8, border_radius: [2.0;4].into() },
color:Color::from_rgb8(13, 248,44),
border_width:1.0,
border_color:Color::BLACK,
}
}
}
}
看一下自定义的效果:
和默认的放一起对比下:
区别还是很明显的,也可以将滑动块设置为圆形,关于样式就差不多了。
接下来说一下本例中slider的应用,即拖动slider时,其值改变,实时值会在下方的文本text中显示,同时,对滑动条的值进行转换,作为上方text的尺寸倍率,即拖动slider时,上方文本的大小会随之改变,看一下实际效果:
这里的实现也很简单,即获取slider的实时值后,将其进行转换,然后将转换的倍率和text文本的size值相乘即可:
let scale1=self.value_sld /20.0;
let size1=15.0*scale1;
text(format!("value:{}",self.value)).size(size1).shaping(Shaping::Advanced)
.horizontal_alignment(alignment::Horizontal::Center)
.vertical_alignment(alignment::Vertical::Center)
.width(40).height(40).style(style7),