前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Rust Druid 之Controller 控制器使用

Rust Druid 之Controller 控制器使用

原创
作者头像
8菠萝
修改2021-05-24 10:48:27
1.3K0
修改2021-05-24 10:48:27
举报
文章被收录于专栏:菠萝上市没有

目的

了解Druid 中如何控制Widget的各种界面事件。

概念

Druid 做为数据驱动的GUI 框架, 它的设计分为三层:

Widget 负责界面展示渲染, Lens 负责各界面的数据传递, Controller 则负责各种事件的处理逻辑。

可以把Controller理解成一个事件拦截器,用于处理Widget的事件,它的源码实现也是使用代理模式。

当使用对一个widget对象使用 controller 方法,它会放回一个ControllerHost的代理对象, 内部会调用我们定义的Controller对象方法。

fn controller<C: Controller<T, Self>>(self, controller: C) -> ControllerHost<Self, C> {

ControllerHost::new(self, controller)

}

ControllerHost 部分源码:

代码语言:javascript
复制
pub struct ControllerHost<W, C> {
    widget: W,
    controller: C,
}

impl<W, C> ControllerHost<W, C> {
    /// Create a new `ControllerHost`.
    pub fn new(widget: W, controller: C) -> ControllerHost<W, C> {
        ControllerHost { widget, controller }
    }
}

impl<T, W: Widget<T>, C: Controller<T, W>> Widget<T> for ControllerHost<W, C> {
    fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
        // 处理方法
        self.controller
            .event(&mut self.widget, ctx, event, data, env)
    }
    //... 略
}

实践

界面上有两个TextBox, 当TextBox_1 输入文本时, TextBox_2 输出 TextBox_1的反转文本。

Cargo.toml

[dependencies]

druid = { git = "https://github.com/linebender/druid.git", features=["image", "png"]}

代码语言:javascript
复制
use druid::{Event, lens, text, widget::{Button, Controller, SizedBox}};
use druid::WidgetExt;
use druid::{
    widget::{Flex, TextBox},
    AppLauncher, Data, Size, Widget, WindowDesc,
};

#[derive(Data, Clone, Debug)]
pub struct DataText {
    pub data: String,	   
    pub data_rev: String,  // 保存反转
}

// 控制器声明
struct TextBoxController;

// 实现Event键盘事件拦截
impl <W:Widget<DataText>> Controller<DataText, W> for TextBoxController {
    fn event(&mut self, child: &mut W, ctx: &mut druid::EventCtx, event: &druid::Event, data: &mut DataText, env: &druid::Env) {
        if let Event::KeyUp(e) = event {
            // 反转
            data.data_rev = data.data.chars().rev().collect::<String>();
        }
        child.event(ctx, event, data, env)
    }

    fn lifecycle(
        &mut self,
        child: &mut W,
        ctx: &mut druid::LifeCycleCtx,
        event: &druid::LifeCycle,
        data: &DataText,
        env: &druid::Env,
    ) {
        child.lifecycle(ctx, event, data, env)
    }

    fn update(&mut self, child: &mut W, ctx: &mut druid::UpdateCtx, old_data: &DataText, data: &DataText, env: &druid::Env) {
        child.update(ctx, old_data, data, env)
    }
}

fn buid_root() -> impl Widget<DataText> {
    let s1 = lens!(DataText, data);
    let s2 = lens!(DataText, data_rev);
    // 设置控制器
    let text_box_up= TextBox::multiline().lens(s1).controller(TextBoxController{});
    let text_box_down = TextBox::multiline().lens(s2);
    let clear_btn = Button::new("Clear").on_click(|_ctx, data: &mut DataText, _env| data.data = "".to_string());
    Flex::column()
    .with_flex_child(text_box_up.expand(), 1.0)
    .with_flex_child(text_box_down.expand(), 1.0)
    .with_child(Flex::row().with_flex_child(SizedBox::empty().fix_height(20.0).expand_width(), 1.0).with_child(clear_btn))
}

fn main() {
    let m = DataText {
        data: "Hello".to_string(),
        data_rev: "World".to_string()
    };
    let w = WindowDesc::new(buid_root()).window_size(Size::new(400.0, 400.0));
    AppLauncher::with_window(w).log_to_console().launch(m).unwrap();
}

运行结果:

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目的
  • 概念
  • 实践
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档