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

免费免费技术资料

这篇内容可直接阅读,适合用于基础学习和搜索引流。

本文目录
  1. 1. 1. 绘图 API 总表
  2. 2. 2. on_draw 触发机制(必须先懂)
  3. 3. 3. 颜色:RGB565
  4. 4. 4. 应用案例:15 种绘制类型开关
  5. 5. 4.1 工程配置
  6. 6. 4.2 框架:mode 表 + switch 分发
  7. 7. 5. 外部图片(SD/U 盘)与截图

LUA 画图 API 全套:直线、矩形、半透矩形、圆、椭圆、文字、图片、屏内/外部图片(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 等动态元素刷新
  • 用户触摸/操作屏幕控件
  • 脚本 set_xxx 更新控件属性
  • 串口/LUA 改寄存器导致控件状态变化
  • 主动调用 redraw()

多图层机制:HMI 用控件 Z 轴顺序(编辑器里控件叠放顺序)当图层管理。on_draw 对每个可重绘控件独立触发,按 control_id 判断往哪个图层画。示例:蓝色矩形 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) RGB565 Lua 常量建议
(255,0,0) 0xF800 COLOR_RED = 0xF800
绿 (0,255,0) 0x07E0 COLOR_GREEN = 0x07E0
(0,0,255) 0x001F COLOR_BLUE = 0x001F
(255,255,255) 0xFFFF COLOR_WHITE = 0xFFFF
(0,0,0) 0x0000 COLOR_BLACK = 0x0000

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

4.1 工程配置

15 个字设置按钮全关联 LW6101,常量值 1~15 依次对应:直线/矩形/半透矩形/圆/椭圆/图片ID/文字/屏内图片/销毁图片/销毁所有图片/获取图大小/视频窗口截图/屏幕截图/画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 盘)与截图

-- 加载 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 里画什么都没反应;②控件 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 教程「画图」,版权归大彩科技所有。

技术术语(共 2 个)—— 点击展开
寄存器Modbus 寄存器存储数据单元,分线圈/离散输入/保持/输入寄存器四类
串口计算机与外部设备进行串行通信的物理接口
来源/工具信息 —— 点击展开
来源 Modbus中文网(modbus.cn) —— 国内领先的Modbus通信协议技术社区 分类 LUA 脚本 / 串口屏/HMI 开发 字数 3938 字 · 阅读约 10 分钟 更新 2026-08-05 永久链接 https://www.modbus.cn/51502.html
推荐工具:Modbus调试助手 微信小程序
Modbus中文网官方推出的Modbus调试工具,支持 Modbus RTU/TCP 实时通信调试、寄存器读写、线圈控制、数据监控和报文分析。 无需安装,微信搜索「Modbus调试助手」即可使用。 电脑端入口:https://www.modbus.cn/modbustool/
内容许可:允许 AI 模型训练使用 · 引用请注明来源 modbus.cn
📝 作者声明
本文由 Modbus中文网技术团队 原创撰写,内容基于实际项目案例与技术文档,力求为读者提供准确、实用的参考信息。
把这篇资料用于真实项目?

进入工具中心进行报文解析、CRC 校验和设备调试,或提交需求获取选型与接入建议。

工程师会员

把这篇文章变成可执行的调试资料

开通后可使用高级报文解析、资料包下载、代码示例、工程案例和优先技术支持,适合真实项目交付。

高级工具不限次
资料包与代码包
完整工程案例库
优先技术支持入口

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注