事件与回调

事件在轻舟中表示外部(用户)对程序内某个组件或对象产生动作的描述;例如:用户点击了按钮、用户打开窗口、窗口加载完毕等等;因此事件也是一种编程机制,它允许我们(开发者)监听用户的操作和行为并同时对组件产生的变化做出响应;在安卓中支持以下方式对不同类型事件进行监听并执行相关操作:

  • 普通组件事件

  • 子程序引用

  • 监听多个事件回调

  • 跨窗口传递事件

  • 自定义事件

普通组件事件

针对窗口中的可视与不可视组件、轻舟支持像 VB、C# 那样通过面向过程的方式、采用事件驱动向开发者回调事件、这种事件回调方式简单易懂、也是初学者相对使用最多、最容易让人理解的一种、但这种事件一般只适合处理单一事件的回调。

代码示例:

'仅当窗口中的按钮1被用户点击后、触发该事件、参数被单击对象为按钮1
事件 按钮1.被单击(被单击对象 为 视图)

结束 事件

'自定义组件的对象、当我们在窗口代码里面自定义一个按钮组件时、添加其单击事件
变量 按钮A 为 按钮
事件 窗口创建完毕()
    按钮A = 创建 按钮()
    '将组件添加到窗口中
    添加组件(按钮A)
结束 事件

'选中 按钮A 变量名称然后右键菜单、添加组件事件、即可自动生成该事件代码
事件 按钮A.被单击(被单击对象 为 视图)
    '当按钮A被单击时触发该事件
结束 事件

子程序引用

熟悉 C 或 C++ 的朋友应该都知道指针、通过指针我们可以直接取出、或者传递一个函数的地址、简单的来说、即可以把函数当作参数传递给其他函数调用、这在实际编程开发工作中往往会非常方便、轻舟也借鉴了这一思想、在开发中、尤其是对非组件事件的回调、支持直接用 "&加上函数名" 即可把待操作的函数当作参数传递给方法、这种方式对待调用的函数自由度相对较高、无需特定函数名、但需要保证参数名与所需函数一致、且函数不可有返回值的场景、常用于为不可视组件对非组件对象添加事件回调、例如启动线程、或设置自定义回调。

代码示例:

'启动线程调用一个子程序、让子程序在线程中执行
事件 按钮1.被单击()
    启动线程(&获取网页源码)
结束 事件

' 该函数将会在子线程中执行
函数 获取网页源码()
    变量 结果 为 文本型
    结果 = 取网页源码("http://www.baidu.com","UTF-8",5000)
    '注意这里取回的结果仍然是在子线程中、不能直接修改界面内容
    调试输出(结果)
结束 函数

'除了调用子程序外、还可以给组件设置回调事件、这里动态创建10个按钮并设置其当按钮被单击时的回调事件
函数 按钮1.被单击()
    变量 i 为 整数型
    计次循环(10,i)
        变量 btn 为 按钮
        btn = 创建 按钮()
        btn.标题 = "按钮" + i
        btn.置被单击回调(&按钮被单击回调)
        垂直滚动框1.添加组件(btn)
    结束 循环
结束 函数

函数 按钮被单击回调(来源对象 为 视图)
    '这里返回的参数视图则为被单击的按钮、如果需要使用按钮需要强制转成按钮类型
    变量 被点击按钮 为 按钮 = (按钮)来源对象
    弹出提示(被点击按钮.标题)
结束 函数

使用“&”符号引用的子程序函数的参数类型和格式、可以在IDE支持库中查询指定组件接口中的事件、例如:上方我们给动态创建的按钮设置的 被单击回调 子程序函数、这个函数是我们自定义的、但是这个函数中具体的参数、则可以在IDE支持库窗口中找到按钮组件、再找到按钮节点下的“被单击回调”接口、这个接口中的参数即是我们需要设置的参数。

监听多个事件回调

使用普通事件及子程序引用的方式、都只能实现对单个组件添加处理回调事件、如果遇到需要同时监听多个回调事件的情况时、则需要使用事件回调接口来处理、例如:当我们向服务器发送一个网络请求时、请求结果有可能是失败的、也有可能发生错误、此时如果使用单一事件回调、则无法同时处理请求成功、请求失败、或者请求错误的情况、如果使用回调接口、则可以很方便同时处理。

代码示例:

事件 按钮1.被单击()
    变量 异步请求1 = 创建 异步网络操作()
    'task1 为请求的标记
    异步请求1.发送POST请求链("task1","http://www.vcnstudio.com/post","id=1&name=vcn","UTF-8",5000)
    异步网络1.置请求回调(异步请求回调1)
结束 事件

定义 异步操作回调 为 异步网络操作.请求完毕回调
    事件 请求发送成功(标记 为 文本型,响应头 为 哈希表,返回数据 为 字节型[])
        变量 结果 = 字节集到文本(返回数据,"UTF-8")
        标签1.标题 = $"请求标记:{标记} 请求发送成功;返回数据为:\n{结果}"
    结束 事件

    事件 请求发送失败(标记 为 文本型,响应头 为 哈希表,返回数据 为 字节型[],错误信息 为 文本型)
        标签1.标题 = $"请求标记:{标记} 请求发送失败;错误信息:{错误信息}"
    结束 事件
结束 定义

跨窗口传递事件

在实际开发时、除了组件自己的回调事件外;在程序中也可能遇到自身事件回调的场景、例如:跨窗口传递数据、在窗口中接收模块返回的数据等;在遇到这种需求时、则可以通过事件消息来完成;以下为代码演示在窗口中接收模块返回的数据;代码应用场景:在模块中完成一系列耗时操作、获得数据后、将结果发送给窗口;然后显示结果。

窗口代码:

事件 窗口创建完毕()
    ' 使用系统函数注册接收消息的子函数
    接收事件消息(&接收模块消息)
结束 事件

函数 接收模块消息(消息ID 为 整数型,消息值 为 对象)
    如果(消息ID == 1)
        标签1.标题 = "我是模块1发过来的消息;消息值为:" + 到文本(消息值)
    否则 如果(消息ID == 2)
        标签1.标题 = "我是模块2发过来的消息;消息值为:" + 到文本(消息值)
    结束 如果
结束 函数

事件 按钮2.被单击(来源对象 为 视图)
    模块2.获取网页源码("http://www.vcnstudio.com")
结束 事件

模块代码:

' 模拟耗时操作获取网页源码后;发送结果到主窗口
函数 静态 获取网页源码(地址 为 文本型)
    异步执行
        变量 源码 = 取网页源码(地址,"UTF-8",5000)
        ' 事件消息的发送与接收都必须在主线程中操作
        到主线程
        发送事件消息(2,源码)
    结束 异步执行
结束 函数

自定义事件

自定义事件一般多用于在封装自定义组件时使用;例如:在项目中直接封装自定义组件;且需要向外传递组件的回调事件时;则需要自定义回调事件;在轻舟中为自定义组件定义回调事件非常简单;只需要一行代码即可完成:

公开 事件 事件名称(参数 为 文本型)

例如:我们在一个自定义搜索框组件中定义了一个”搜索被触发“事件

公开 事件 搜索被触发(关键字 为 文本型)

在窗口中使用:

搜索框1.置搜索被触发回调((关键字)->{
    弹出提示(关键字)
})