LittleVgl,一款开源嵌入式图形用户界面库。https://littlevgl.cn/
使用简单小巧,界面也漂亮。很适合用在嵌入式上。在Stm32单片机上都能跑,只要实现了基础的函数很好移植。
业余时间移植到了嵌入式linux上,使用帧缓冲Frambuffer,显示效果还不错。
计划选用LittleVgl作为嵌入式的漂亮的UI。
其他GUI如QT,miniGUI,周立功的AWTK也都有了解过。界面UI是强大,但是就是有点儿庞大,在简单的嵌入式界面上不想花太多精力和时间。毕竟不是手机,不需要太多人机交互,要的是简单小巧,够用即可。
之前本想在Ubuntu14上玩儿一下AWTK,但是编译依赖一大堆,最后放弃了。查看官网才知道需要使用Ubuntu16以上系统且安装好几个不知道什么用途的依赖,后续有机会再尝试吧。他们能不能出个纯c代码的精简版?可能太强大和支持N多平台的缘故吧,代码依赖很多三方库,这点儿有点儿不让人喜欢,不够小巧。
如图:
但是,还是不够好用。
计划使用go加上面向对象的思想,对其进行进一步的封装,让其更简单好用一点儿。
如果使用上类似于python上的绑定那样简单的话,该是多么美好的事情,如:
$ python3
Python 3.6.5 (default, May 9 2018, 10:02:20)
[GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> from pylvgl import Demo, lvgl
>>> d = Demo()
>>>
>>> b1 = lvgl.Btn(lvgl.scr_act())
>>> b1.set_size(200,50)
>>> b1.align(b1.get_parent(), lvgl.ALIGN_IN_LEFT_MID, 0, 0)
>>>
>>> l1 = lvgl.Label(b1)
>>> l1.set_text('LittlevGL')
>>>
>>> lm = lvgl.Lmeter(lvgl.scr_act())
>>> lm.align(cal.get_parent(), lvgl.ALIGN_IN_LEFT_MID, 300, 0)
>>> lm.set_range(0,100)
>>> lm.set_value(10)
>>>
>>> style_lm1.line_width = 4
>>> style_lm1.body_main_color = 0x2200
>>> style_lm1.body_grad_color = 0x0022
>>> lm.set_style(style_lm1)
>>>
>>> lb2 = lvgl.Label(lm)
>>> lb2.set_text('10%')
>>> lb2.align(lm, lvgl.ALIGN_CENTER, 0, 0)
已经初步验证了,go的绑定可行,使用也变得简单啦
如:
package main
import (
"golvgl/lvgl"
"log"
"time"
)
func main() {
log.Println("Hello Go,LittlevGL")
lb := lvgl.Label(lvgl.ScrAct(), nil)
lb.SetText("hello world,go test 222")
lb.Align(nil, lvgl.LV_ALIGN_CENTER, 0, 0)
log.Println("Hello Go Over 222")
for true {
lvgl.TickInc(5)
lvgl.TaskHandler()
time.Sleep(5000)
}
}
随后代码会放在 github上,希望感兴趣的有志之士能一块儿参与完善下封装。
https://github.com/yangyongzhen/golvgl.git
package lvgl
/*
#cgo CFLAGS: -Iinclude/lvgl
#include "lvgl.h"
#cgo LDFLAGS: -Llibs -llvgl
#include <stdlib.h>
extern void disp_init(void);
extern void fbdev_init(void);
extern void fbdev_flush(void);
void disp_init(){
lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.disp_flush = fbdev_flush;
lv_disp_drv_register(&disp_drv);
}
*/
import "C"
import "unsafe"
// Lvobj ...
type Lvobj C.struct__lv_obj_t
const (
LV_ALIGN_CENTER C.uchar = C.LV_ALIGN_CENTER
)
func init() {
C.lv_init()
C.fbdev_init()
C.disp_init()
}
// ScrAct ...
func ScrAct() *Lvobj {
return (*Lvobj)(unsafe.Pointer(C.lv_scr_act()))
}
// Label ...
func Label(par, copy *Lvobj) *Lvobj {
var p1 *C.struct__lv_obj_t
var p2 *C.struct__lv_obj_t
p1 = (*C.struct__lv_obj_t)(unsafe.Pointer(par))
p2 = (*C.struct__lv_obj_t)(unsafe.Pointer(copy))
return (*Lvobj)(unsafe.Pointer(C.lv_label_create(p1, p2)))
}
// SetText ...
func (obj *Lvobj) SetText(str string) {
C.lv_label_set_text((*C.struct__lv_obj_t)(unsafe.Pointer(obj)), C.CString(str))
}
// Align ...
func (obj *Lvobj) Align(base *Lvobj, align C.uchar, x int, y int) {
var ba *C.struct__lv_obj_t
ba = (*C.struct__lv_obj_t)(unsafe.Pointer(base))
C.lv_obj_align((*C.struct__lv_obj_t)(unsafe.Pointer(obj)), ba, align, C.short(x), C.short(y))
}
// TickInc ...
func TickInc(tick int) {
C.lv_tick_inc(C.uint(tick))
}
// TaskHandler ...
func TaskHandler() {
C.lv_task_handler()
}
其中遇到的问题总结:
void * 对应go中的unsafe.Pointer
c结构体和 go之间的转换为:
var obj *Lvobj
var p *C.struct__lv_obj_t
p = (*C.struct__lv_obj_t)(unsafe.Pointer(obj))
byte[]和 c的数组之间转换为:
var img_bubble_pattern_map = []byte{0,1,2}
(*C.uchar)(unsafe.Pointer(&img_bubble_pattern_map[0])
c结构体的位域和go之间转换为:
var img_bubble_pattern C.lv_img_dsc_t
var img_bubble_pattern_map = []byte{
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53}
const (
LV_ALIGN_CENTER C.uchar = C.LV_ALIGN_CENTER
)
func init() {
fmt.Println(img_bubble_pattern)
fmt.Println(reflect.TypeOf(img_bubble_pattern))
//fmt.Println(reflect.TypeOf(img_bubble_pattern.header.always_zero))
bt := [4]byte{0, 1, 2, 3}
img_bubble_pattern = C.lv_img_dsc_t{
header: C.lv_img_header_t{bt},
data_size: 112320 * C.LV_COLOR_SIZE / 8,
data: (*C.uchar)(unsafe.Pointer(&img_bubble_pattern_map[0])),
}
}
未完待续,敬请期待....