VisualHMI 画图:on_draw/redraw/绘图 API 与分层绘制

freeFree Technical Resource

This content is free to read, suitable for basic learning and search traffic.

LUA 画图 API 全套:直线、矩形、半透矩形、圆、椭圆、文字、Image、屏内/外部图片(SD/U 盘)、截图。核心机制是 on_draw(screen, control) 控件级自绘回调——所有 draw_xxx 指令必须在 on_draw 里调用才生效。适用 HMI&M 시리즈&Dx 시리즈。

1. 绘图 API 总表

函数파라미터说明
set_pen_color(color)RGB565 颜色设置画笔前景色,作用于线条/边框/轮廓/文本描边
draw_line(x0,y0,x1,y1,width)width 1~10画直线,颜色取当前画笔
draw_rect(x0,y0,x1,y1,fill)fill 1=填充/0=边框矩形,x0,y0 左上角,x1,y1 右下角
draw_rect_alpha(x0,y0,x1,y1,alpha)alpha 0~255半透明实心矩形,0=全透/255=不透明,做遮罩层
draw_circle(x,y,r,fill)fill 0=实心/非0=空心(值为线宽)画圆,x,y 圆心,r 半径
draw_ellipse(x0,y0,x1,y1,fill)外接矩形两角,fill 同上画内切于矩形的椭圆
draw_image(image_id,frame_id,dstx,dsty,w,h,srcx,srcy)image_id 查 build/image.xml;frame_id 动画帧画工程图片资源,支持缩放和裁剪
draw_text(text,x,y,w,h,font_id,size,color,align,charcode)align 0左/1中/2右;charcode 0=UTF-8/1=GBK区域内画文字
load_surface(filename)JPEG/PNG 路径加载外部图片返回句柄(不走 image.bin)
draw_surface(surface,dstx,dsty,w,h,srcx,srcy)surface 句柄画已加载的外部图片,支持裁剪缩放,必须在 on_draw 里调
destroy_surface(surface)句柄释放单个图层资源
destroy_all_surface()-批量释放所有已加载图层
get_surface_size(surface)句柄获取图层原始像素宽高
clear_image_buffer()-释放内部图片资源缓存
screen_shoot(filepath)完整路径含扩展名当前画面存为 JPEG

2. on_draw 触发机制(必须先懂)

on_draw(screen_id, control_id) 是系统回调,用户不得直接调用。control_id 必须 ≠ 0,否则自绘功能无效。触发条件:

  • 画面含动画、视频、RTC 等动态元素刷新
  • 用户触摸/操作屏幕控件
  • Script set_xxx 更新控件属性
  • 시리얼 포트/LUA 改寄存器导致控件状态变化
  • 主动调用 redraw()

多图层机制:HMI 用控件 Z 轴顺序(编辑器里控件叠放顺序)当图层管理。on_draw 对每个可重绘控件独立触发,按 control_id 判断往哪个图层画。example:蓝色矩形 ID=10 在下层画「水果」,黄色矩形 ID=11 在上层画「小岛」,黄色会盖住蓝色部分。

function on_draw(screen_id, control_id)
  if screen_id == 0 and control_id == 1 then
    draw_surface(surface[1], 293, 88, 222, 353, 0, 0)  -- 裁剪显示
  elseif screen_id == 0 and control_id == 2 then
    draw_surface(surface[2], 314, 158, 180, 250, 0, 0)
  end
end

3. 颜色:RGB565

所有颜色参数都是 16 位 RGB565:高 5 位 Red(0~31)、中 6 位 Green(0~63)、低 5 位 Blue(0~31),范围 0x0000~0xFFFF。

颜色RGB(888)RGB565Lua 常量建议
(255,0,0)0xF800COLOR_RED = 0xF800
绿(0,255,0)0x07E0COLOR_GREEN = 0x07E0
(0,0,255)0x001FCOLOR_BLUE = 0x001F
(255,255,255)0xFFFFCOLOR_WHITE = 0xFFFF
(0,0,0)0x0000COLOR_BLACK = 0x0000

4. 应用案例:15 种绘制类型开关

4.1 工程配置

15 个字设置按钮全关联 LW6101,常量值 1~15 依次对应:直线/矩形/半透矩形/圆/椭圆/ImageID/文字/屏内图片/销毁图片/销毁所有图片/获取图大小/视频窗口截图/屏幕截图/画SD图/画U盘图片。15 个位状态指示灯关联 LW6100 切画笔颜色。

4.2 框架:mode 表 + switch 分发

penColor = {0xF800, 0x001F}      -- 红、蓝
CUR_COLOR = 0xF800                -- 初始颜色
draw_type = 0                     -- 当前绘制类型

mode = {                          -- 绘制类型表
  line = 1, rect = 2, rect_alpha = 3, circle = 4, ellipse = 5,
  imageId = 6, text = 7, surface_path3 = 8, destroyOne = 9,
  destroyAll = 10, getSurface = 11, videoShoot = 12,
  screenShoot = 13, surface_pathsd = 14, surface_pathusb = 15
}

function on_update(slave, vtype, addr)
  if addr == 0x6100 then
    CUR_COLOR = penColor[get_uint16(VT_LW, addr) + 1]  -- 切画笔
  elseif addr == 0x6101 then
    draw_type = get_uint16(VT_LW, addr)                -- 切绘制类型
  end
  redraw()                                              -- 触发重绘
end

function on_draw(screen_id, control_id)
  set_pen_color(CUR_COLOR)
  local switch = {
    [mode.line] = function(control)                    -- 键值1
      draw_line(225, 253, 405, 253)                    -- 默认宽度1
      draw_line(508, 128, 508, 378, 5)                 -- 宽度5
    end,
    [mode.rect] = function(control)                    -- 键值2
      draw_rect(225, 128, 225+180, 128+250, 0)         -- 不填充
      draw_rect(418, 163, 418+180, 128+180, 1)         -- 填充
    end,
    [mode.rect_alpha] = function(control)              -- 键值3
      draw_rect_alpha(225, 128, 225+180, 128+250, 200) -- 透明度200
      draw_rect_alpha(418, 163, 418+180, 128+180, 230) -- 透明度230
    end,
    [mode.circle] = function(control)                  -- 键值4
      draw_circle(300, 253, 100, 0)                    -- 实心
      draw_circle(450, 253, 150, 1)                    -- 空心(线宽1)
    end,
    [mode.ellipse] = function(control)                 -- 键值5
      draw_ellipse(225, 128, 225+180, 128+250, 0)      -- 实心
      draw_ellipse(418, 163, 418+180, 128+180, 1)      -- 空心
    end,
    [mode.text] = function(control)                    -- 键值7
      draw_text("VisualHMI", 100, 300, 200, 40,
                0, 24, CUR_COLOR, 1, 0)               -- 居中 UTF-8
    end,
  }
  if switch[draw_type] then
    switch[draw_type](control)
  end
end

5. 外部图片(SD/U 盘)与截图

-- load SD 卡图片(load_surface 支持 JPEG/PNG)
if draw_type == mode.surface_pathsd then
  surface[1] = load_surface("1:/pic.png")
  redraw()
end

-- on_draw 里绘制
if draw_type == mode.surface_pathsd then
  if surface[1] then
    draw_surface(surface[1], 225, 128, 180, 250, 0, 0)
  end
end

-- 截图到 SD 卡
if draw_type == mode.screenShoot then
  screen_shoot("1:/shot.jpg")
end

用 load_surface 加载的外部图片不进工程 image.bin,是运行期从文件系统读。用完必须 destroy_surface 释放,否则内存泄漏;大图或带透明通道的 PNG 特别吃内存。

五个坑:①draw_xxx 必须在 on_draw 回调里调用才生效,在 on_update 里画什么都没反应;②control ID ≠ 0,0 号控件不触发自绘;③draw_circle/draw_ellipse 的 fill 语义和 draw_rect 相反——圆和椭圆 0=实心、非0=空心,矩形 1=填充/0=边框,别记混;④draw_image 的 image_id 查工程 build/image.xml,不是文件名;⑤外部图片用完就 destroy_surface,HMI 内存小,泄漏多了直接崩。

整理自 广州大彩科技 VisualHMI 开发文档(hmi-doc.gz-dc.com)LUA Tutorial「画图」,版权归大彩科技所有。

Put this resource to use in a real project?

Go to the Tool Center for message parsing, CRC 검증 and device debugging, or submit your requirements for selection and integration advice.

Engineer Membership

Turn this article into actionable debugging resources

After activation, you can use advanced message parsing, resource pack downloads, code examples, engineering cases and priority technical support, suitable for real project delivery.

Unlimited Advanced Tools
Resource & Code Packs
Complete Engineering Case Library
Priority Technical Support

Leave a Reply

Your email 주소 will not be published. Required fields are marked *.