rust语言orbtk GUI基础(old2018)-3.1 orbtk基础控件

orbtk的api在2019.2进行了修改,该文章为2018版
新版请转[新版orbtk gui基础]

rust orbtk基础widgets

  • orbtk基础控件demo
  • orbtk控件使用方法
    • orbtk控件原理
    • 创建控件
      • 为控件添加子控件
      • 设置属性
      • 添加状态和事件处理器
      • render设置
      • 控件外观
    • 通用属性
    • TextBlock控件主要属性
    • WaterMarkTextBlock控件
    • textbox
    • button
    • checkbox
    • switch
    • image
    • FontIconBlock
  • 本文代码

orbtk基础控件demo

orbtk目前内置的控件并不多,基础控件主要有:

  • TextBlock
  • TextBox
  • Button
  • ToggleButton
  • check_box
  • Switch
  • FontIconBlock
  • ImageWidget
  • WaterMarkTextBlock//貌似目前(2019.1)还有问题,不能正常显示

首先,我们先创建一个包含基础控件的窗口,看看效果:

use orbtk::*;
use styling::vector_graphics::material_font_icons::CHECK_FONT_ICON;

fn main() {
    let mut application = Application::default();

    //创建控件
    let text_block = TextBlock::create().with_property(Label::from("textblock"));
    let text_box = TextBox::create().with_property(Label::from("textbox"));
    let water_mark_text_box = TextBox::create().with_property(WaterMark::from("watermark..."));
    let btn = Button::create().with_property(Label::from("button"));
    let toggle_btn = ToggleButton::create().with_property(Label::from("togglebutton"));
    let switch = Switch::create();
    let check_box = CheckBox::create().with_property(Label::from("checkbox"));
    let font_icon_block = FontIconBlock::create().with_property(FontIcon::from(CHECK_FONT_ICON));
    let image_widget = ImageWidget::create()
        .with_property(Image::from_path("src/bin/img/home.png").unwrap_or(Image::default()));
    let water_mark_text_block = TextBlock::create()
        .with_property(Label::from(""))
        .with_property(WaterMark::from("textblockmark..."));
    let water_mark_text_block2 = WaterMarkTextBlock::create()
        .with_property(Label::from(String::new()))
        .with_property(WaterMark::from("yyyy..."));

    //所有控件放入Row布局控件中
    //直接把所有控件加入rootde Template控件会重叠
    //所以把所有控件都放在一个layout控件中
    let column = Column::create()
        .with_child(text_block)
        .with_child(text_box)
        .with_child(water_mark_text_box)
        .with_child(btn)
        .with_child(toggle_btn)
        .with_child(switch)
        .with_child(check_box)
        .with_child(font_icon_block)
        .with_child(image_widget)
        .with_child(water_mark_text_block)
        .with_child(water_mark_text_block2);

    //rootde parent_tyep可以设置为Multi,但是控件会重叠
    //所以初学者,建议root就设置为single,root只放一个layout控件
    let root = Template::default()
        .as_parent_type(ParentType::Single)
        .with_child(column);

    application
        .create_window()
        .with_bounds(Bounds::new(100, 100, 320, 260))
        .with_title("OrbTk - Widgets")
        .with_resizable(true)
        .with_root(root)
        //.with_debug_flag(true)
        .build();
    application.run();
}

当然,上述代码只是为了方便入门学习,可以用更加Rustacean的方式写代码:

use orbtk::*;
use styling::vector_graphics::material_font_icons::CHECK_FONT_ICON;

struct MainView;

impl Widget for MainView {
    fn create() -> Template {
        Template::default()
            .as_parent_type(ParentType::Single)
            .with_child(
                Column::create()
                    .with_child(TextBlock::create().with_property(Label::from("textblock")))
                    .with_child(TextBox::create().with_property(Label::from("textbox")))
                    .with_child(TextBox::create().with_property(WaterMark::from("watermark...")))
                    .with_child(Button::create().with_property(Label::from("button")))
                    .with_child(ToggleButton::create().with_property(Label::from("togglebutton")))
                    .with_child(Switch::create())
                    .with_child(CheckBox::create().with_property(Label::from("checkbox")))
                    .with_child(
                        FontIconBlock::create().with_property(FontIcon::from(CHECK_FONT_ICON)),
                    )
                    .with_child(ImageWidget::create().with_property(
                        Image::from_path("src/bin/img/home.png").unwrap_or(Image::default()),
                    ))
                    .with_child(
                        TextBlock::create()
                            .with_property(Label::from(""))
                            .with_property(WaterMark::from("textblockmark...")),
                    )
                    .with_child(
                        WaterMarkTextBlock::create()
                            .with_property(Label::from(String::new()))
                            .with_property(WaterMark::from("yyyy...")),
                    ),
            )
    }
}

fn main() {
    let mut application = Application::default();

    application
        .create_window()
        .with_bounds(Bounds::new(100, 100, 320, 260))
        .with_title("OrbTk - Widgets")
        .with_resizable(true)
        .with_root(MainView::create())
        //.with_debug_flag(true)
        .build();
    application.run();
}

cargo run编译运行后显示窗口如下:

rust语言orbtk GUI基础(old2018)-3.1 orbtk基础控件_第1张图片

orbtk控件使用方法

orbtk控件原理

orbtk所有控件的定义都是空结构体,即:

pub struct TextBlock;
pub struct Button;
pub struct Row;

orbtk所有控件都实现了Widget trait,并且目前所有控件都只实现了这一个trait。Widget trait也只有一个方法create()。

impl Widget for TextBlock {
    fn create() -> Template {
        ...
    }
    
impl Widget for Row {
    fn create() -> Template {
        ...
    }

也就是说目前所有orbtk控件都只包含一个create方法。这个create方法返回一个Template。创建控件的时候事实上就是使用create方法创建一个Template。我们可以看到上节代码中使用Button::create(),TextBox::create()等等创建控件。

设置控件属性也是使用Template的with_property()方法来设置的。所有的控件都是Template的实例,只是不同控件的属性及默认render不同。每个orbtk控件都在create()方法中设置了默认的render,orbtk绘制窗口的时候调用默认的render根据Template的属性绘制控件树。

orbtk自定义控件,就相当于新建一个Template并设置相关属性。难点主要在于render是否需要重写。

创建控件

所有的控件都使用create()方法创建,比如:

let btn=Button::create();
let text_block=TextBlock::create();

控件都通过Template的方法进行属性设置,主要包括

为控件添加子控件

使用with_child()方法添加子控件,比如:

Row::create().with_child(btn);

添加多个子控件可以多次调用with_child()方法,支持链式调用。

Row::create().with_child(btn).with_child(text_block);
//也可以
let row=Row::create().with_child(btn);
let row=row.with_child(text_block)

注意helloworld节已经提到的,Template有一个parent_type成员,其值表示能够添加多少个子控件。

  • parent_type值为ParentType::None,不能添加子控件
  • parent_type值为ParentType::Single,只能添加一个子控件,如果已经有一个子控件,则覆盖/替换
  • parent_type值为ParentType::Multi,可以添加任意多个子控件

为Template控件添加子控件之前都必须先设置一下parent_type。方法为as_parent_type()

Template::default().as_parent_type(ParentType::Single)

orbtk内置的控件都有默认的parent_type值,添加子控件前不用再设置。比如TextBlock为None,Container为Single,Row为Multi。

设置属性

使用with_property()方法设置属性

btn.with_property(Label::from("button"));

可以多次调用with_property()方法多次设置属性。

大家可以看到设置属性的时候并没有提供属性的名称,Template是根据属性类型来分辨不同属性的。所以Template中不同的属性都是不同的类型。

这也就是为什么Button在设置Label属性的时候不直接使用String,而使用一个Label结构把String包装起来的原因。Label的定义事实上就是pub struct Label(pub String)

Template还有一个with_shared_property方法,这个shared_property我们后边再讲。

添加状态和事件处理器

with_state()with_event_handler()两个方法分别用于添加状态和事件处理器,都是用于处理用户交互的,后续再讲。

render设置

with_render_object()with_layout()两个方法分别用于添加render和layout。都是和绘制控件相关的,所有orbtk内建的控件都设置了默认的render和layout,入门学习可以暂时不用管这两个方法。

控件外观

orbtk控件支持使用css样式,每个控件都可以通过设置selector属性来关联css选择器。

样式我们后续再讲讲。

通用属性

所有控件都支持的属性:

  • Bounds:设置控件位置和大小
  • Visibility:设置是否可见
  • Selector:设置css关联的选择器,class等
btn.with_property(Bounds::new(20,20,20,20));
btn.with_property(Visibility::Hidden);//控件不可见
btn.with_property(Visibility::Collapsed);//控件不可见,且不占位置
btn.with_property(
    Selector::from("button").with_class("primary")
)//css中使用button选择器,primary class定义btn的样式

TextBlock控件主要属性

TextBlock控件的功能就是现实文本,不能编辑,不能交互。

TextBlock通常只需要设置Label属性

TextBlock::create().with_property(Label::from("textblock"));

WaterMarkTextBlock控件

WaterMarkTextBlock控件类似TextBlock,但是会在Label属性为空的时候现实WaterMark属性的内容。

WaterMarkTextBlock控件主要属性包括:

  • Label
  • WaterMark
WaterMarkTextBlock::create()
    .with_property(Label::from("textblock"))
    .with_property(WaterMark::from("wartermark..."));

目前事实上TextBlock设置WaterMark属性后和watermarktextblock效果一样。
以下两种代码效果相同:

WaterMarkTextBlock::create()
    .with_property(Label::from(String::new()))
    .with_property(WaterMark::from("yyyy..."));

TextBlock::create()
    .with_property(Label::from(""))
    .with_property(WaterMark::from("textblockmark..."));

但是watermarktextblock貌似有bug,只有在WaterMarkTextBlock后方没有控件的时候才能正常显示,否则会被后方控件遮住。把WaterMarkTextBlock放在container或者Row中也会出现被裁剪的问题,大家可以试一下。

textbox

TextBox是一个文本框,可以交互输入。主要属性有

  • Label:文本框中的文字
  • WaterMark:文本框中没有文字是显示watermark
  • Focused:是否是当前控件
  • Enabled:是否可用,false时不能输入
TextBox::create()
    .with_property(WaterMark::from("watermark..."))
    .with_property(Focused(true))
    .with_property(Enabled(false))

貌似目前TextBox还不能用小键盘输入。

button

Button控件是个按钮控件,ToggleButton是一个开关型按钮。主要属性有:

  • Label:按钮上的文本
  • FontIcon:按钮上的图标
  • Pressed:是否按下
  • Enabled:是否可用
Button::create()
    .with_property(Label::from("btn"))
    .with_property(FontIcon::from(CHECK_FONT_ICON))
    .with_property(Pressed(true))
    .with_property(Enabled(false))

checkbox

checkbox的主要属性有

  • Label:文本
  • FontIcon:选中时方框内显示的图标,默认为√
  • Selected:是否选中
  • Enabled:是否可用
CheckBox::create()
    .with_property(Label::from("checkbox"))
    .with_property(FontIcon::from(FLOPPY_FONT_ICON))
    .with_property(Selected(true))
    .with_property(Enabled(true))

switch

  • PrimaryFontIcon:打开状态时的图标
  • SecondaryFontIcon:关闭时的图标
  • Selected:是否选中

属性设置方法和checkbox相同,大多数时候只需要设置Selected属性就ok了。

image

ImageWidget用于显示图片,主要属性为Image

ImageWidget::create()
    .with_property(
        Image::from_path("src/bin/img/home.png").unwrap_or(Image::default())
    )

FontIconBlock

FontIconBlock显示一个FontIcon图标,图标为font内的特殊字体。

use styling::vector_graphics::material_font_icons::{CHECK_FONT_ICON, FLOPPY_FONT_ICON};
FontIconBlock::create().with_property(FontIcon::from(CHECK_FONT_ICON))

FontIcon::from()的参数实际上是一个&str,所以可以这样用:

FontIconBlock::create().with_property(FontIcon::from(""))

本文代码

本文代码在https://github.com/hustlei/RustGuiOrbtkTutorial

可以使用下面命令编译运行

cargo run --bin widgets
cargo run --bin primitive_widgets

你可能感兴趣的:(rust)