rust语言orbtk GUI入门-3.1 orbtk基础控件

   2023-02-09 学习力0
核心提示:rust orbtk基础widgetsorbtk基础控件demoorbtk控件使用方法orbtk控件原理创建控件为控件添加子控件设置属性添加状态和事件处理器render设置控件外观通用属性TextBlock控件主要属性WaterMarkTextBlock控件textboxbuttoncheckboxswitchimageFontIconBlock本文代

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入门-3.1 orbtk基础控件

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
 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • bloom-server 基于 rust 编写的 rest api cache 中间件
    bloom-server 基于 rust 编写的 rest api cache
    bloom-server 基于 rust 编写的 rest api cache 中间件,他位于lb 与api worker 之间,使用redis 作为缓存内容存储, 我们需要做的就是配置proxy,同时他使用基于share 的概念,进行cache 的分布存储,包含了请求端口(proxy,访问数据) 以及cache 控制端口(
    03-08
  • #新闻拍一拍# Oracle 调研如何避免让 Java 开发者投奔 Rust 和 Kotlin | Linux 中国
    #新闻拍一拍# Oracle 调研如何避免让 Java 开发
     导读:• 英特尔对迟迟不被 Linux 主线接受的 SGX Enclave 进行了第 38 次修订 • ARM 支持开源的 Panfrost Gallium3D 驱动本文字数:977,阅读时长大约:1分钟作者:硬核老王Oracle 调研如何避免让 Java 开发者投奔 Rust 和 KotlinOracle 委托分析公司 Omd
    03-08
  • Linux系统下Rust快速安装:国内镜像加速
    Linux系统下Rust快速安装:国内镜像加速
    官方网址和方法Install Rust - Rust Programming Language然而速度慢得让人难以置信。利用国内镜像进行windows的Linux子系统的Rust安装。rust 使用国内镜像,快速安装方法参考:RUST安装慢怎么办,使用镜像方式安装_网络_为中华之崛起而编程-CSDN博客我的操作
    03-08
  • Rust到底值不值得学--Rust对比、特色和理念
    前言其实我一直弄不明白一点,那就是计算机技术的发展,是让这个世界变得简单了,还是变得更复杂了。当然这只是一个玩笑,可别把这个问题当真。然而对于IT从业者来说,这可不是一个玩笑。几乎每一次的技术发展,都让这个生态变得更为复杂。“英年早秃”已经成
    03-08
  • 超33000行新代码,为Linux内核添加Rust支持的补丁已准备就绪
    超33000行新代码,为Linux内核添加Rust支持的补
    https://mp.weixin.qq.com/s/oKw9aBJSdmRoO6-rbLAkNw7 月 4 日,一套修订后的补丁被提交至 Linux 内核的邮件列表中,该补丁为在 Linux 内核中以 Rust 作为辅助编程语言提供了支持,借助 Rust 可以提高 Linux 内核和内存的安全。整套补丁包含 17 个子项,不光
    03-08
  • 【译】Rust 的 Result 类型入门
    【译】Rust 的 Result 类型入门
    A Primer on Rust’s Result Type 译文原文链接:https://medium.com/@JoeKreydt/a-primer-on-rusts-result-type-66363cf18e6a原文作者:Joe Kreydt译文出处:https://github.com/suhanyujie/article-transfer-rs译者:suhanyujietips:水平有限,翻译不当之
    03-08
  • Rust实战系列-基本语法
    Rust实战系列-基本语法
    主要介绍 Rust 的语法、基本类型和数据结构,通过实现一个简单版 grep 命令行工具,来理解 Rust 独有的特性。本文是《Rust in action》学习总结系列的第二部分,更多内容请看已发布文章:一、Rust实战系列-Rust介绍“主要介绍 Rust 的语法、基本类型和数据结
    03-08
  • 全栈程序员的新玩具Rust(三)板条箱
    上次用到了stdout,这次我们来写一个更复杂一点的游戏rust的标准库叫做std,默认就会引入。这次我们要用到一个随机数函数,而随机数比较尴尬的一点是这玩意不在标准库中,我们要额外依赖一个库。很多编程方案都有自己的模块化库系统,rust也不例外,不过rust
    02-10
  • 全栈程序员的新玩具Rust(六)第一个WASM程序
    全栈程序员的新玩具Rust(六)第一个WASM程序
    先上代码https://gitee.com/lightsever/rust_study/tree/master/wasm_hello01webassembly就不用再赘述了,耳朵里面快磨出茧子来了。rustwasm是火狐自家的玩具,让我们来继续做实验,让rust飞起来吧。环境安装安装好rust环境之后仍然需要 一个 wasm 工具包carg
    02-10
  • 【Rust】标准库-Result rust数据库
    环境Rust 1.56.1VSCode 1.61.2概念参考:https://doc.rust-lang.org/stable/rust-by-example/std/result.html示例main.rsmod checked {#[derive(Debug)]pub enum MathError {DivisionByZero,NonPositiveLogarithm,NegativeSquareRoot,}pub type MathResult =
    02-09
点击排行