AWTK开发UI简单入门XML篇

AWTK 开发 UI 简单入门—XML 篇

一,前序

  在上一篇文章中( AWTK 开发 UI 简单入门 C 语言篇)让大家明白 AWTK 的 UI 入门了,但是如果纯用 C 语言写 UI 会出现比较多的问题,其中比较严重的是无法把 UI 设计和程序逻辑分开,现在主流的 GUI 类库都是采用了 XML 的前端设计加上主流语言的后端逻辑的思路,例如 WPF 和 android,同时 AWTK 也支持 XML 的前端设计加上 C 语言的后端逻辑的思路,下面我们就来演示一下如何使用 XML 来做 UI 设计和 C 语言逻辑绑定吧。

备注:本文中采用的例子为 ZLG 提供的 HelloWorld.Xml-Demo 项目为原型,而文本只是把项目改为使用 vs 的项目,而不是原项目采用的 scons 而已,下面附上对应项目的 github 地址:

  1. ZLG 提供 HelloWorld.Xml-Demo 项目的 github 地址:https://github.com/zlgopen/awtk-examples
  2. 修改后的 HelloWorld.Xml-Demo 项目的 github 地址:https://github.com/WNsACE/CSDN_AWTK_DEMO

二,构建项目

  由于上一篇文章中已经详细描述了如何使用 vs 来构造一个 AWTK 的项目,所以这里就不逐一描述了。(如果大家不清楚的话,建议看回上一篇文章)

  1. 构建一个名为 HelloWorld.Xml-Demo 的 vs 项目
  2. 把项目中设置为 x64
  3. 把 ZLG 提供 HelloWorld.Xml-Demo 项目中的 src 文件夹和 res 文件夹拷贝到新的 HelloWorld.Xml-Demo 的 vs 项目目录下,并且把 src 文件夹下的 SConscript 文件删除(其实不删除也可以,只是本人的强逼症 0.0),如图:
    在这里插入图片描述
  4. 然后把 src 文件中的 app_main.c 和 window_main.c 文件加入到 vs 项目中。
  5. 设置窗口的子系统类型,如下图:(因为窗口类型会调用 WinMain 函数作为函数入口,控制台类型会调用 main 函数作为函数入口)
    在这里插入图片描述

备注:如果不设置这里有可能会先链接不到对应的函数入口。

  1. 设置项目头文件路径和宏。

备注:宏设置的时候,需要把 WITH_FS_RES 宏设置到项目中,下面会讲述这个 WITH_FS_RES 宏的作用。

  1. 设置项目类库路径和对应的类库。

备注:加入类库中,需要把 extwidgets.lib 类库加入到项目中,因为代码中调用到 tk_ext_widgets_init 函数,所以需要加入 extwidgets.lib 类库,但是该项目中没有用到该类库中的控件,所以也可以删除 tk_ext_widgets_init 函数,而不是加入 extwidgets.lib 类库。

  1. 修改项目的输出目录为 $(ProjectDir)bin\ ,如下图:
    在这里插入图片描述

备注:

  1. 这里设置 vs 项目中的输出目录是为了配合原来 ZLG 的 demo 代码(因为完全没有修改 ZLG 的代码)。
  2. 这里一定需要注意的是 AWTK 和 ZLG 的 demo 代码一定要最新的,要不然会出现各种奇怪的问题,甚至崩毁的问题。(这个原因主要是因为 AWTK 在 1 月头的时候更新了资源相关的代码,导致旧的资源不能被新的 AWTK 使用导致的。)

  把项目配置完后,直接运行就可以看到效果了,接下来会一步一步来解析上面的配置原理和代码中的逻辑,让大家可以更好的理解。

三,解释配置原理

  上面的所有配置都是为了配置原来 ZLG 提供的 demo 代码,所以接下来我们一起来理解一下吧。

1. 为什么需要加入 WITH_FS_RES 宏到项目中

   WITH_FS_RES 宏在 AWTK 中是用于启用文件系统的,让程序可以通过文件系统加载到文件。同时我们打开 res/assets.inc 文件,该文件用来加载需要的文件,本文暂时不解释该文件中的各种头文件的意义,我们这里是解释 assets.inc 文件中的 assets_init 函数(assets_init 函数在 app_main.c 文件中的 main 函数中有被调用)中的,通过 WITH_FS_RES 宏来调用预加载函数(assets_manager_preload 函数)来把 default 风格资源和 default 字体资源加载到程序中,然后通过 tk_init_assets 函数来把对应的资源挂载到对应的资源管理器中,如下图:
在这里插入图片描述

备注:如果程序系统中支持文件系统的话,请加入 WITH_FS_RES 宏,如果不加入 WITH_FS_RES 宏的话,资源会变成全局静态数组添加到 AWTK 的资源管理器中,这里不展开来讲述,留在下一章节讲资源的时候再展开来讲。

2. 为什么输出目录为 $(ProjectDir)bin\

   有人会问,明明在 main 函数中设置的是程序运行的目录下的 res 目录作为资源目录的,为什么输出目录却设置为项目目录下的 bin 目录,因为 AWTK 中有个机制如果找不到指定的资源目录的话,同时如果程序的运行目录是在 bin 目录的话,会查找 bin 文件夹的同级目录下的 res 文件夹,并把该 res 文件夹作为资源目录,所以方便后面用户直接把 bin 文件夹和 res 文件夹一起拷贝出来发布。
   同时因为 vs 的程序运行目录刚好是项目目录( 项目目录是 $(ProjectDir) ),所以在程序调试的时候,在 main 函数中设置的资源目录刚好把项目下的 res 文件夹设置资源目录,同时发布出来的程序会输出到项目目录( 项目目录是 $(ProjectDir) )下的 bin 文件夹中。

四,关键代码解释

   上面都是讲述如何配置环境和项目,现在讲的是如何让程序加载 XML 的 UI 设计。

1. 编写 XML 的 UI 设计代码

   首先打开资源目录下 UI 文件夹 ( res\assets\default\raw\ui 文件夹),在这个目录下已经有 main.xml 和 main.bin 文件,这两个文件是原来项目中的 XML 的 UI 文件。

注意:在 AWTK 程序中是不会直接读取 XML 文件的,需要把 XML 文件转换到 bin 文件才可以被 AWTK 程序读取,所以换句话来说,我们需要编写 XML 文件,然后通过 AWTK 提供的工具把 XML 文件转换到 bin 文件。

  我们打开 main.xml 文件,如下图代码:(懂 XML 的朋友看到下面应该会感觉到很熟悉的感觉吧)

<window anim_hint="htranslate" >
    <image draw_type="icon" image="awtk_logo" x="right:10" y="10" w="100" h="26"/>
    <label name="label_4_edit" x="c" y="20%" w="30%" h="40" text="hello world" />
    <edit name="edit" x="c" y="40%" w="60%" h="40" text="hello world" input_type="email" />
    <button name="dec_btn" x="20%" y="60%" w="20%" h="40" text="dec"/>
    <label name="label_4_btn" x="c" y="60%" w="20%" h="40" text="88"/>
    <button name="inc_btn" x="60%" y="60%" w="20%" h="40" text="inc"/>
</window>

   这里解释一下,在上一篇文章讲说,AWTK 本身就是一颗控件树,而在 XML 文件中通过节点来表示一个树,所以这里我们可以看到 XML 文件中的顶级节点是 window 类型,而 window 类型的子集就是 image,label,button等控件(window_manager 是默认创建,而且 window 类型默认会被设置为 window_manager 对象的子集)。
   这里我们可以看到 image 控件(图片控件)的 x 坐标为"right:10","right:10"的意思是屏幕最右边往左边偏移 10 像素点,那么我们把这个 x 坐标修改为 " 10 ",意思是屏幕最左边往右边偏移 10 像素点(因为 AWTK 的左上角是(0,0))。
   然后通过 AWTK 的 xml_to_ui 工具把 XML 文件转为 bin 文件,该工具在 AWTK 源码的目录下 bin 文件夹中(之前需要完整的编译 AWTK 的代码),工具的命令选项为:

xml_to_ui.exe in_filename out_filename [bin]

备注:xml_to_ui 工具

  1. 第一个参数为需要转换的 XML 文件路径
  2. 第二个参数为转换后的 bin 文件保存路径
  3. 第三个参数为可选项,不设置的话(或者输入非 bin 的其他字符串的话) bin 文件中保存的是静态数组的代码,如果设置 bin 的话,bin 文件保存为二进制格式。
    在有文件系统的系统中(开启 WITH_FS_RES 宏)程序会加载二进制格式,所以需要设置第三个参数,加入 bin 字符串。

   打开命令行,设置命令行当前工作目录为资源目录下 UI 文件夹 ( res\assets\default\raw\ui 文件夹),然后输入下面就可以生成新的 bin 文件,然后运行程序,可以发现图片控件的位置发生改变了。(自行替换 AWTK 目录的路径)

AWTK目录\xml_to_ui.exe main.xml main.bin bin
2. 代码调用 XML 的 UI

   虽然上面已经写好了 XML 文件并且也转换了 bin 文件,但是有没有想过程序到底是怎样知道到底是调用哪个 UI 文件呢?因为在资源目录下 UI 文件夹 ( res\assets\default\raw\ui 文件夹)还有其他的 UI 文件(bin 文件)。
   下面我们来看一下代码是如何正确的调用指定的 UI 文件的,打开项目中的 window_main.c 文件,我们可以看到 application_init 函数有调用了 window_open 函数。

/**
 * @method window_open
 * @annotation ["constructor", "scriptable"]
 * 从资源文件中加载并创建window_base对象。本函数在ui_loader/ui_builder_default里实现。
 *
 * @param {const char*} name window的名称。
 *
 * @return {widget_t*} 对象。
 */
widget_t* window_open(const char* name);

   我们可以很清楚的看到 window_open 函数就是打开一个名为 main 的 UI 文件,而这个名为 main 的 UI 文件正是上面我们通过 xml_to_ui.exe 工具生成的 bin 文件,所以我们可以理解就是 window_open 函数可以把资源目录下 UI 文件夹 ( res\assets\default\raw\ui 文件夹)中的 bin 文件转换为代码中的窗口对象。
   虽然可以通过 window_open 函数把窗口对象创建出来,但是我们还需要把窗口对象中的各个的子对象通过 widget_on 函数(该函数在 AWTK 开发 UI 简单入门 C 语言篇中有解释过)绑定到对应的功能函数中,所以可以通过 widget_foreach 函数来遍历窗口对象的所有子对象。

/**
 * @method widget_foreach
 * 遍历当前控件及子控件。
 * @annotation ["scriptable:custom"]
 * @param {widget_t*} widget 控件对象。
 * @param {tk_visit_t} visit 遍历的回调函数。
 * @param {void*} ctx 回调函数的上下文。
 *
 * @return {ret_t} 返回RET_OK表示成功,否则表示失败。
 */
ret_t widget_foreach(widget_t* widget, tk_visit_t visit, void* ctx);

   把所有的控件都绑定好对应的功能函数后,这个过程是我们常说的 MVC结构了,UI 文件(bin 文件)为前端,通过 widget_on 函数把所有的控件和逻辑都绑定在一起,后面如果只是 UI 的简单修改就可以直接修改 UI 文件(bin 文件)即可,不需要修改代码原来的逻辑。

五,总结

  本文章是为了解释如何修改 XML 文件和生成 UI 文件(bin 文件)来给大家演示 AWTK 的通过 XML 文件做 UI 设计,建议大家可以按照上面的步骤一边写代码一边理解上面的文字,这样会让大家更好的理解。
  同时这篇文件是为下一篇文件的AWTK 的资源系统篇做一个过度引导的作用。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
AWTK开发手册-AWTK开发实践指南-中文手册.pdf AWTK = Toolkit AnyWhere 随着手机、智能手表等便携式设备的普及,用户对 GUI 的要求越来越高,嵌入式系统对高性能、高可靠性、低功耗、美观炫酷的 GUI 的需求也越来越迫切,ZLG开源 GUI 引擎 AWTK 应运而生。AWTK 全称为 Toolkit AnyWhere,是 ZLG 倾心打造的一套基于 C 语言开发GUI 框架。旨在为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的 GUI 引擎,并支持跨平台同步开发,一次编程,终生使用。 最终目标: 支持开发嵌入式软件。 支持开发Linux应用程序。 支持开发MacOS应用程序。 支持开发Windows应用程序。 支持开发Android应用程序。 支持开发iOS应用程序。 支持开发2D游戏。 其主要特色有: 小巧。在精简配置下,不依赖第三方软件包,仅需要32K RAM + 256K FLASH即可开发一些简单的图形应用程序。 高效。采用脏矩形裁剪算法,每次只绘制和更新变化的部分,极大提高运行效率和能源利用率。 稳定。通过良好的架构设计和编程风格、单元测试、动态(valgrind)检查和Code Review保证其运行的稳定性。 丰富的GUI组件。提供窗口、对话框和各种常用的组件(用户可以配置自己需要的组件,降低对运行环境的要求)。 支持多种字体格式。内置位图字体(并提供转换工具),也可以使用stb_truetype或freetype加载ttf字体。 支持多种图片格式。内置位图图片(并提供转换工具),也可以使用stb_image加载png/jpg等格式的图片。 紧凑的二进制界面描述格式。可以手工编辑的XML格式的界面描述文件,也可以使用Qt Designer设计界面,然后转换成紧凑的二进制界面描述格式,提高运行效率,减小内存开销。 支持主题并采用紧凑的二进制格式。开发时使用XML格式描述主题,然后转换成紧凑的二进制格式,提高运行效率,减小内存开销。 支持裸系统,无需OS和文件系统。字体、图片、主题和界面描述数据都编译到代码中,以常量数据的形式存放,运行时无需加载到内存。 内置nanovg实现高质量的矢量动画,并支持SVG矢量图。 支持窗口动画、控件动画、滑动动画和高清LCD等现代GUI常见特性。 支持国际化(Unicode、字符串翻译和输入法等)。 可移植。支持移植到各种RTOS和嵌入式Linux系统,并通过SDL在各种流行的PC/手机系统上运行。 脚本化。从API注释中提取API的描述信息,通过这些信息可以自动生成各种脚本的绑定代码。 支持硬件2D加速(目前支持STM32的DMA2D和NXP的PXP)和GPU加速(OpenGL/OpenGLES/DirectX/Metal),充分挖掘硬件潜能。 丰富的文档和示例代码。 采用LGPL协议开源发布,在商业软件中使用时无需付费。 目前核心功能已经完成,内部开始在实际项目中使用了,欢迎有兴趣的朋友评估和尝试,期待您的反馈。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值