在上一步中,我们将不同的组件拆分成不同的模块,增加了代码的可维护性。在这一步中,我们将实现在网格模式下点击图片时候,自动切换到 slideshow 模式。
我们会分两步来进行:
action
。action
并跳转到放映模式。这一步,我们将重点放在如何使用 action
实现组件之间的通信上。
注意: 如果你不想自己敲代码,可以在这里找到本步骤的完整代码: https://github.com/Project-Robius-China/image-viewer-workshop
在本步骤中,你将学习:
action
处理组件之间的通信。让我们先在 ImageItem
中,定义 action
,关于 action
的讲解在处理事件中做过讲解。
在 image_item.rs
中,定义 ImageClickedAction
:
这里定义了 ImageClickedAction
用于处理图片点击事件,它是一个枚举,有两个字段: Clicked(usize)
和 None
。这里我们讲解一下关于在 Makepad 中 action
的定义和使用:
如前面章节中讲到,action
是 Makepad 中进行组件之间通信的一个重要方式。正如上面所见,Makepad 中 action
是以枚举的形式出现,你可以在这个枚举中定义你想要响应的用户动作。
Makepad 中,将 事件 event
和 动作 action
进行了区分:
event
: 用于处理各种系统事件。action
: 用于处理用户事件。这样可以更好的控制协调各种事件,并且在代码层级解耦,增加代码的可维护性。
一般的,我们要为创建的 action
实例实现三个 trait:
Clone
: 确保 action
在传递过程中可以克隆。Debug
: 方便打印调试 action
。DefaultNone
: action
在默认情况下值为 None
。这三个trait 也是 Makepad 的默认 action
开发规范。
在 image_item.rs
文件中,用下面的代码替换 ImageItem 结构体的定义:
这为 ImageItem 结构体增加了以下字段:
image_index
: 父组件 ImageRow
设置,用于表示当前的图片的索引。在 handle_event
中,用下面的代码替换:
event.hits()
返回一个枚举 Hit
,其中封装了常见的鼠标事件,所以这里我们使用 match 来进行匹配,Hit::FingerUp(_)
表示当我们点击鼠标左键手指抬起时的动作,也就是我们鼠标点击事件。这里我们只使用到了鼠标的点击事件,所以对于其他事件,我们使用 _
进行统一处理。
cx.action
是传递 action
的方式,这里我们我们定义好的 action
传入这个函数。在 action
中带上我们设置的 image_index
字段,确保根组件能够正确获取到从那一张图片进行放映。
cx.action()
: 这是最基础的 action
发送方法。适用于你需要在当前执行上下文中发送一个简单的、非特定 widget
的消息。它不携带额外的widget信息,不需要路径信息,就是纯粹的消息传递。cx.widget_action()
: 需要传入详细的 widget_uid
以及 path
,包含了详细的发送者信息、路径信息和 action
,适用于需要确定 action
是由某一个 widget
发送的情况。Cx::post_action()
: 是一个静态方法,主要适用于如何从后台线程安全地向UI线程发送 action
的情况。切换放映模式是在根组件下控制,所以我们要在 app.rs
下处理,在 handle_actions()
中增加一下代码:
for action in actions {...}
是将 action
从 参数 actions
中遍历出来。action.cast()
将遍历处的 action
进行投射,直到拿到我们设定的 ImageClickedAction::Clicked(image_idx)
, 进行接下来的处理。
之后调用 set_current_image()
来把点击的图片设置为当前需要播放的图片,之后开启放映模式,设置页面焦点,与我们直接点击放映按钮的功能一致。
注意: 如果你是使用
cx.widget_action()
来传递action
,那么相应的,你也应该使用action.as_widget_action()
来接收action
。
让我们检查一下到目前为止的进展。
确保你当前在你的包目录下,然后运行:
如果一切正常,那么当鼠标点击图片,就可出现放映效果。