与其说是go之旅,不如说是C,计算机世界的霸主C语言,有人可能说是汇编(ASM)才是,亲我说的是高级语言哈。不要抬杠,很多语言都是基于C的,搞了很多类C语言。

golang想绘制GUI,必然涉及交叉编译。

废话不多说,今天的主角是https://github.com/idea4good/GuiLite

GuiLiteGuiLite设计原理及代码注释
  • 基本原理
  • 扩展方法
  • 代码目录结构
  • 界面元素管理
  • 图形绘制
  • 文件注释
  • 函数注释
  • 速成路线图

基本原理

GuiLite只作两个工作:界面元素管理和图形绘制。

界面管理包括:

  • 添加/删除界面元素(例如:按钮,标签,对话框等控件),设置对应的文字及位置信息
  • 用户输入消息传递:根据用户输入寻找受影响的界面元素,并回调响应的处理的处理函数
  • 用户自定义消息传递:用户可以自定义消息响应函数,并自主产生消息;当消息产生时,对应的响应函数会被调用

图形绘制包括:

  • 基本的点线绘制,例如:画点,矩形,横线,竖线等
  • 设置绘制图层,如果需要多个图层,在基本点线绘制时,需要给出图层的索引值
  • 图层处理,在图层界面发生变化的时候(例如:打开/关闭对话框),GuiLite将决定各个图层上的像素点,哪个会被最终显示在屏幕上

?注意:图形绘制不依赖界面管理,可以独立的存在,例如,在资源有限的单片机环境,有时候不需要界面元素管理,而直接进行图形,文字的绘制。

扩展方法

GuiLite只给出了基本控件(例如:按钮,标签,键盘,选择框)的实现方法,旨在说明控件的实现方法。对于扩展控件,可以选择下面的方式:

  • 如果开发者需要调整基本控件的细节,可以直接在源代码中修改
  • 如果开发者需要构建全新的控件,可以参考基本控件的实现方法,重新实现

对于扩展绘制,例如:画圆,画曲线,可以直接在surface.cpp文件中添加响应的函数接口。

代码目录结构

core:

  • 实现了底层绘制,图层管理和消息传递
  • adapter实现了各个平台(例如:Windows, Linux,Android,iOS,macOS,未知OS或无OS)的封装。

widgets:

  • 实现了各种常规控件(例如:按钮,标签,键盘,波形)及容器(例如:视窗,对话框,滑动页面),开发者可以根据自己的需要,直接在相应的代码上进行修改或重绘,开发出有自己风格,特色的界面
  • 实现了用户的手势识别(例如:手指滑动,鼠标按下/释放)的消息传递,将用户的输入信息传递到整个GUI体系树中,并调用相应的响应回调函数;开发者可以根据自己的需要添加/修改响应回调函数。

界面元素管理

界面元素管理包括:对所有控件(button,spinbox, lable, keyboard),容器(dialog, view)管理;具体的管理方法是在用户调用connect函数时,会把所有的界面元素连接起来,从而实现对所有界面元素的遍历/添加/删除等操作。这些链接看起来像一棵树,对界面元素的遍历,就是对这棵树的遍历

比如:当你按下一个dialog的button时,手指的位置信息(x,y)会被传入树的根部(root),然后从root开始寻找,哪个dialog被点中,dialog的哪个button被点中,并调用buton被点中的回调函数,用于作相应处理(一般会进行button的状态修改及重绘工作)

界面元素如何创建

所有界面元素都继承自c_wnd类的对象,对象被实例化时,也就完成了界面元素的创建;但此时的界面元素是孤独的,与其他界面元素没有形成联系(没有父母,没有兄弟姐妹)

界面元素如何被管理

新创建的界面元素纳入管理的过程,就是为其添加父母,兄弟姐妹的过程。使用的函数接口为connect();从此该界面元素会跟其他界面元素一样,纳入一棵树中,并随之响应用户可能的点击操作。

当需要删掉该界面元素时,使用disconnect();从此该界面元素会断绝所有的父子关系,从树上摘下来,不再响应用户的触控操作;但对象本身不会被销毁。典型应用场景:软键盘的创建/退出。

图形绘制

图形绘制包括: 绘制方法和图层管理。

  • 点绘制是线/面/位图绘制的基础,若干个点的绘制,形成点面及位图
  • 图层管理,则是管理多个界面元素的遮挡关系,系统默认支持3层遮挡关系,这3个层次可以为:视图背景层,对话框层,keyboard/spinbox控件层。

绘制方法

请参看文件bitmap.cpp和surface.cpp中的draw_xxx()函数。 为了发挥GPU的加速功能,也可以通过改写draw_xxx/fill_xxx函数,使用GPU特性,来提升绘制效率。

图层管理

  • display层:该层对应了物理显存,display层决定了一个显示终端的最终显示效果;通常系统中至少有一个display层。
  • surface层:该层属于display层的一个部分;它为左右滑动而存在,每一张滑动页面均对应了一个surface层;surface层决定了一个滑动页面的最终显示效果;通常1个display层会对应多个surface层。
  • frame层:该层属于surface层的一个部分;它现实叠加界面元素而存在。

文件注释


函数注释



速成路线图

  1. 精读源文件wnd.cpp中的connect, on_touch, on_key函数,理解界面元素的串联办法;理解响应触控操作的基本原理;理解响应硬按键的基本原理
  2. 快速浏览surface.cpp中用于绘制的draw_xxx函数,熟悉基本的绘制接口;精读c_surface构造函数,理解c_surface类的各种成员关系
  3. 精读button.cpp文件,初步掌握界面元素的基本开发方法
    • 快速浏览HelloStar实例的BuildLinux/main.cpp,理解构建一般Linux应用的办法
    • 快速浏览HelloStar实例的BuildMFC/HelloStarDlg.cpp,理解构建一般Windows应用的办法
    • 快速浏览HelloStar实例的BuildSTM32F103-Keil/USER/main.c,理解构建一般单片机系统的办法