VisualHMI - 画图

本章节主要介绍LUA脚本使用API进行线、矩形、圆、椭圆、文字、图片等

适用范围:VisualHMI - HMI&M系列&Dx系列

例程下载链接:ViusalHMI - 画图(点击下载)

1.Lua API说明

3.1.on_draw(screen,control)

on_draw 是 HMI 系统提供的控件级自绘回调接口,用于在指定画面的特定控件区域上执行用户自定义的图形绘制。开发者可on_draw函数里调用各类 draw_xxx 图形 API,实现图片、文字、图形(点、线、几何图形)的绘制

📊 参数说明

参数 类型 说明
screen_id number 当前画面 ID
• 表示触发重绘的界面编号
• 可用于区分不同画面的绘制逻辑
control_id number 触发重绘的控件 ID
• 表示需要自绘的控件唯一标识
• 必须 ≠ 0

⚠️ 注意

  1. 该函数为系统回调函数,用户不得直接调用
  2. 所有 draw_xxx 图形绘制指令(如 draw_linedraw_surface 等)必须在此函数内调用才能生效;
  3. 控件ID ≠ 0 ,否则自绘功能无效。
3.1.1.触发条件 on_draw
  • 界面包含动画、视频、RTC 时间等动态元素刷新;

  • 用户触摸或操作屏幕控件;

  • 脚本通过 set_xxx更新控件属性;

  • 串口/LUA 指令修改寄存器,从而修改控件状态;

  • 主动调用 redraw()

3.1.2. 多图层绘制机制

核心原理

HMI 系统采用控件 Z 轴顺序(即界面编辑器中的控件叠放顺序)作为天然的图层管理机制。on_draw(screen_id, control_id) 回调函数在每个可重绘控件独立触发,开发者可通过判断 control_id,将不同的图形内容绘制到对应控件图层(控件叠放上下关系),从而实现逻辑上的“分层叠加”

关键设计:控件在界面中的上下排列顺序直接决定了最终视觉的图层叠加顺序

典型图层结构示例

假设界面从底到顶包含以下元素(Z 轴顺序由低到高):

图层层级 元素类型 实现方式 作用
下层 蓝色背景区域 ID = 10 的矩形控件(蓝色填充) 作为“水果图层”的容器
上层 黄色背景区域 ID = 11 的矩形控件(黄色填充) 作为“小岛图层”的容器

📌 注意

  • 蓝色矩形(ID=10)在编辑器中位于黄色矩形(ID=11)下方,因此视觉上被后者部分覆盖;
  • 两个矩形均启用自绘功能(ID ≠ 0),系统将在各自区域触发 on_draw

image-20231107105022458

当系统刷新界面时:

  1. 遍历所有需重绘的控件(按 Z 轴从底到顶);
  2. 对每个支持自绘的控件,调用一次 on_draw(screen_id, control_id)
  3. 开发者通过 control_id判断当前绘制目标:
    • control_id == 10 → 在蓝色矩形区域内绘制“水果图片”;
    • control_id == 11 → 在黄色矩形区域内绘制“小岛图片”;
  4. 最终合成效果: 原本画面(底) ← 蓝色背景 + 水果(中) ← 黄色背景 + 小岛(顶)

image-20231107105443307

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.2.redraw()

全局界面重绘触发函数,redraw() 是 HMI 系统提供的全局重绘请求接口,用于主动触发当前画面所有支持自绘的控件执行 on_draw 回调函数,强制刷新界面显示内容。

3.3.set_pen_color(color)

设置绘图画笔颜色set_pen_color(color) 是 HMI 系统提供的设置画笔颜色函数,用于设置后续所有绘图操作的前景色(画笔颜色),适用于线条、矩形边框、圆形轮廓、文本描边等非填充型或边框型图形的颜色

📊 参数说明

参数 类型 说明
color number 画笔颜色值(RGB565 格式)
• 高 5 位为 Red(0~31)
• 中 6 位为 Green(0~63)
• 低 5 位为 Blue(0~31)
• 取值范围:0x0000(黑)至 0xFFFF(白)
• 用于后续 draw_linedraw_rectdraw_circle 等矢量图形的边框或线条颜色

RGB565 编码示例:

颜色 RGB (888) RGB565 (Hex) 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

3.4.draw_line(x0,y0,x1,y1,width)

直线绘制函数draw_line 是 HMI 绘制一条指定起点、终点及线宽的直线段。该线段颜色依赖当前画笔颜(由 set_pen_color 设定)

📊 参数说明

参数 类型 说明
x0 number 起始点 X 轴坐标: 直线起点的水平位置,取值范围依据实际屏幕分辨率而定
y0 number 起始点 Y 轴坐标: 直线起点的垂直位置,取值范围依据实际屏幕分辨率而定
x1 number 结束点 X 轴坐标 :直线终点的水平位置,取值范围依据实际屏幕分辨率而定
y1 number 结束点 Y 轴坐标 :直线终点的垂直位置,取值范围依据实际屏幕分辨率而定
width number 线条的厚度: 表示绘制直线时线条的宽度,有效取值范围为 1 到 10

3.5.draw_rect(x0,y0,x1,y1,fill)

矩形绘制函数draw_rect 函数是HMI(人机交互界面)开发中常用的绘图接口之一,通过定义左上角和右下角的坐标以及是否填充该矩形,在指定位置绘制一个矩形

📊 参数说明

参数 类型 说明
x0 number 左上角 X 坐标
• 相对于绘图上下文原点(通常是控件或画布的左上角)的水平偏移量
y0 number 左上角 Y 坐标
• 相对于绘图上下文原点的垂直偏移量
x1 number 右下角 X 坐标
• 定义矩形宽度的结束位置
y1 number 右下角 Y 坐标
• 定义矩形高度的结束位置
fill integer 填充标志
• 若值为 1,则使用当前填充色填充整个矩形
• 若值为 0,仅绘制矩形边框

3.6.draw_rect_alpha(x0,y0,x1,y1,alpha)

半透明实心矩形绘制函数draw_rect_alpha 是 HMI 图形系统提供的半透矩形填充绘图接口,用于指定位内绘制一个带有指定透明度的实心矩形。该函数常用于实现遮罩层

📊 参数说明

参数 类型 说明
x0 number 矩形左上角 X 坐标
• 相对于当前控件客户区左上角的像素偏移 • 通常 ≥ 0
y0 number 矩形左上角 Y 坐标
•相对于当前控件客户区左上角的像素偏移 • 通常 ≥ 0
x1 number 矩形右下角 X 坐标
• 必须 > x0,否则矩形无效或不可见
y1 number 矩形右下角 Y 坐标
• 必须 > y0,否则矩形无效或不可见
alpha number 透明度系数
• 有效范围:0 ~ 255
• 0 = 完全透明(不可见)
• 255= 完全不透明
• 中间值实现与背景的 Alpha 混合

3.7.draw_circle(x,y,r,fill)

圆形绘制函数draw_circle 是用于绘制圆形的函数。此函数可以基于提供的中心坐标 (x, y)、半径 r 以及填充标志 fill 来绘制一个指定大小和样式的圆形。根据 fill 参数的不同,该函数可以绘制出轮廓圆(非填充)或实心圆(填充)

📊 参数说明

参数 类型 默认值 说明
x 数字 - 圆的中心点 X 坐标
y 数字 - 圆的中心点 Y 坐标
r 数字 - 圆的半径,决定了圆的大小
fill 数字 0 填充标志:
0 表示填充圆(实心圆)
• 非 0 表示绘制圆周线(空心圆),此时值可作为线条厚度

3.8.draw_ellipse(x0,y0,x1,y1,fill)

椭圆绘制函数draw_ellipse 是 HMI 图形系统提供椭圆绘图接口,用于绘制一个内切于指定矩形区域的椭圆。通过控制填充模式与边框表现,可灵活实现从实心椭圆到带厚度轮廓的空心椭圆

📊 参数说明

参数 类型 说明
x0 number 外接矩形左上角 X 坐标
y0 number 外接矩形左上角 Y 坐标
x1 number 外接矩形右下角 X 坐标
• 必须 > x0
y1 number 外接矩形右下角 Y 坐标
• 必须 > y0
fill number 填充控制标志
0:绘制实心填充椭圆
• 非 0:绘制空心椭圆轮廓,其值通常表示线条厚度(如 fill=2 表示 2 像素粗的边框)

3.9.draw_image(image_id,frame_id,dstx,dsty,width,height,srcx,srcy)

图片绘制函数draw_image 是 HMI系统提供绘制图片资源的接口。此函数允许开发者通过指定图片资源ID、显示位置与大小,以及可选的裁剪区域来灵活地控制图像显示。

📊 参数说明

参数 类型 说明
image_id number 图片资源的唯一标识符
• 标识将要绘制的图片资源;
frame_id number 帧ID
• 对于支持帧动画的图片类型,指明所使用的具体帧;
• 对于非动画图片类型,该值通常固定为0;
dstx number 图片显示的X坐标
• 目标图片左上角相对于客户区左上角的水平偏移量;
dsty number 图片显示的Y坐标
• 目标图片左上角相对于客户区左上角的垂直偏移量;
width number 图片显示的宽度
• 指定图片在屏幕上显示时的宽度,实现缩放效果;
height number 图片显示的高度
• 指定图片在屏幕上显示时的高度,实现缩放效果;
srcx number 图片裁剪的起始X坐标
• 若不希望从图片的原点开始绘制,可以指定从原图的哪个点开始裁剪;
srcy number 图片裁剪的起始Y坐
• 配合srcx,定义裁剪矩形的起点;

[!note|tip:如何确定image_id] 1.在工程目录下的../build/文件夹,打开image.xml文件,image id = "xx"表示第一个参数

image-20231107110143684

3.10.draw_text(text,x,y,w,h,font_id,size,color,align,charcode)

文本绘制函数draw_text 是 HMI 图形系统提供的文字绘制接口,用于在指定区域内绘制字符串。支持自定义字体、字号、颜色、对齐方式及字符编码

📊 参数说明

参数 类型 说明
text string 待显示的文本内容
• 支持 ASCII 及多字节字符(如 UTF-8、GB2312),具体由 charcode 决定
x number 文本区域左上角 X 坐标
y number 文本区域左上角 Y 坐标
w number 文本区域宽度(像素)
h number 文本区域高度(像素)
font_id number 字体资源 ID
• 对应工程中预加载的字体编号(如 0=默认字体,1=自定义矢量字体)
size number 字体大小(像素)
• 表示字体高度
color number 文字颜色(RGB565 格式)
• 高 5 位 Red,中 6 位 Green,低 5 位 Blue • 例如:0xFFFF = 白色,0x0000 = 黑色
align number 文本对齐方式
• 常见值:  0 = 左对齐  1 = 居中对齐  2 = 右对齐 • 部分平台支持垂直对齐组合(需查手册)
charcode number 字符编码类型
• 指定 text 字符串的编码格式,选填。0 或不填,默认 lua 文件 UTF-8 编。1 位 GBK

3.11.load_surface (filename)

图像加载函数,load_surface 用于从指定路径加载 JPEG 或 PNG 格式的图片文件(外部图形,非工程打包的image.bin里的图片资源),并将其作为句柄(surface)返回。surface后续绘图操作中被引用。

📊 参数说明

参数 类型 说明
filename string 待加载的图片文件路径: 支持的格式,JPEG, PNG

⚠️ 关键注意事项

  • 路径准确性:确保提供的 filename 路径准确无误,指向有效的 JPEG 或 PNG 文件。
  • 内存占用:大尺寸图像或大量图像的同时加载会占用较多内存,应注意资源管理。
  • 透明度处理:对于带有透明度信息的 PNG 图像,占用内存比较大

3.12.destroy_surface (surface)

图层资源销毁函数destroy_surface(surface) 用于释放“由 load_surface ”申请的图形资源。调用后,该图层指针失效,不可再用于任何绘图操作

📊 参数说明

参数 类型 说明
surface number 图层资源句柄
• 由 load_surface()、函数返回的有效指针或对象引用

核心用途

  • 防止内存泄漏,尤其在动态加载/卸载图片的场景中;
  • 释放 GPU 或帧缓冲区中缓存的图像数据;
  • 管理有限的嵌入式系统图形资源。

3.13.destroy_all_surface()

批量销毁所有图层资源函数,destroy_all_surface() 是 HMI 图形系统提供的全局图层资源清理接口,用于一次性释放当前脚本上下文中所有已加载的图层(surface)所占用的内存资源。调用后,所有通过 load_surface创建的图层句柄均失效

✅ 核心用途

  • 快速回收全部图像资源,避免逐个管理;
  • 简化资源管理逻辑,防止因遗漏导致的内存泄漏。

3.14.draw_surface (surface,dstx,dsty,width,height,srcx,srcy)

draw_surface是绘制load_surface 申请的图片资源 的接口,将已加载的图层资源(如 JPEG/PNG 图片)绘制到指定位置。支持区域裁剪尺寸缩放。该函数必须在 on_draw 回调中调用才能生效。

📊 参数说明

参数 类型 说明
surface number 图层资源句柄
• 由 load_surface() 返回的有效图像对象
dstx number 目标显示区域左上角 X 坐标
dsty number 目标显示区域左上角 Y 坐标
width number 目标显示宽度(可选)
• 原图将水平缩放至该宽度 • 若省略或设为 0,使用原图宽度
height number 目标显示高度(可选)
• 原图将垂直缩放至该高度 • 若省略或设为 0,使用原图高度
srcx number 源图裁剪起始 X 坐标(可选)
• 从原图 (srcx, srcy) 开始截取内容 • 若省略或设为 0,从原图左上角开始
srcy number 源图裁剪起始 Y 坐标(可选)
• 配合 srcx 定义裁剪起点 • 若省略或设为 0,从原图左上角开始

3.15.get_surface_size (surface)

获取图层尺寸函数get_surface_size(surface) 是 HMI 图形系统提供的图层属性查询接口,用于获取已加载图层(surface)的原始像素尺寸。该函数返回图像的宽度和高度

📊 参数说明

参数 类型 说明
surface number 图层资源句柄
• 由 load_surface() 返回的有效图像对象

3.16.clear_image_buffer()

清除内部图片资源缓存函数clear_image_buffer() 是 HMI 系统提供的全局图像缓存管理接口,用于强制释放图形的图片数据,以降低内存占用

3.17.screen_shoot(filepath)

屏幕截图函数screen_shoot(filepath) 是 HMI 系统提供的屏幕内容捕获接口,用于将当前显示画面(或指定区域)保存为图像文件( JPEG 格式)

📊 参数说明

参数 类型 说明
filepath string 截图保存的完整文件路径
• 必须包含文件名及扩展名(如 1.jpg

2.工程配置

2.1.绘制键设置

添加15个字设置按钮,用于触发Lua绘制按钮,以“直线”按钮为例,控件配置如下所示:

  1. 写入地址:LW6100
  2. 操作模式:写入常量

    • 常量值:1/2/3/4/5/6/7/8/9/10/11/12/13/14/15(依次为直线/矩形/半透矩形/圆/椭圆/图片ID/文字/屏内图片/销毁图片/销毁所有图片/获取图大小/视频窗口截图/屏幕截图/画SD图/画U盘图片)
  3. 使用图库:√
  4. 使用文字:√

image-20240119135457461

2.2.画笔设置

添加15个位状态指示灯,用来设置画笔颜色,黄色/蓝色之前切换,如下所示:

  1. 写入地址:LW6100
  2. 切换开关:√
  3. 开关类型:切换开关

image-20240119140453567

2.3.文本设置

添加一个文本控件,用于显示图片大小,配置如下所示:

image-20240119140954134

3.Lua 脚本

3.1.画笔

在on_update里面,判断触发地址和键值,若地址为LW6100,值为0画笔为蓝色,值为1画笔为红色,代码如下所示:

penColor = {0xF800, 0x001F}
CUR_COLOR = 0xF800 --初始颜色,

function on_update(slave,vtype,addr)

    if addr == 0x6100
    then
        CUR_COLOR = penColor[get_uint16(VT_LW, addr) + 1]
    end
    redraw()
end

function on_draw(screen_id,control_id)
    set_pen_color(CUR_COLOR)
end

3.2.直线

3.2.1.Lua

在on_update里面,判断触发地址和键值,若地址为LW6101,值为1,绘制直线,代码如下所示:

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
        local msg = ''
        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)
            draw_line(508, 128, 508, 378, 5)
        end,
    }

    if switch[draw_type]
    then
        switch[draw_type](control)
    end
end

3.2.2.预览

运行预览,点击直线按钮,绘制宽度为1,和宽度为5的直线,设置画笔颜色,直线颜色随着改变,如下所示:

Video_2024-01-19_143205

3.3.矩形

3.3.1.Lua

在on_update里面,判断触发地址和键值,若地址为LW6101,值为2,绘制矩形,代码如下所示:

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
        local msg = ''
        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.rect] = function(control) --键值2
            draw_rect(225, 128, (225+180), (128+250), 0)--填充
            draw_rect(418, 163, (418+180), (128+180), 1)--不填充
        end,
    }

    if switch[draw_type]
    then
        switch[draw_type](control)
    end
end

3.3.2.预览

运行预览,点击矩形按钮,绘制1个填充,1个不填充的矩形,设置画笔颜色,矩形颜色随着改变,如下所示:

Video_2024-01-19_143445

3.4.半透矩形

3.4.1.Lua

在on_update里面,判断触发地址和键值,若地址为LW6101,值为3,绘制半透矩形,代码如下所示:

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
        local msg = ''
        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.rect_alpha] = function(control)--键值3
            draw_rect_alpha(225, 128, (225+180), (128+250), 200)--0~255透明度
            draw_rect_alpha(418, 163, (418+180), (128+180), 230)--0~255透明度
        end,
    }

    if switch[draw_type]
    then
        switch[draw_type](control)
    end
end

3.4.2.预览

运行预览,点击矩形按钮,绘制两个半透矩形,1个200透明度,1个230透明度,设置画笔颜色,半透矩形颜色随着改变,如下所示:

Video_2024-01-19_145130

3.5.圆形

3.5.1.Lua

在on_update里面,判断触发地址和键值,若地址为LW6101,值为4,绘制圆形,代码如下所示:

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
        local msg = ''
        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.circle] = function(control)--键值4
            draw_circle(300, 253, 100, 0) --填充
            draw_circle(450, 253, 150, 1) --不填充
        }        
    end,

    if switch[draw_type]
    then
        switch[draw_type](control)
    end
end

3.5.2.预览

运行预览,点击圆形按钮,绘制1个填充,1个不填充的圆形,设置画笔颜色,圆形颜色随着改变,如下所示:

Video_2024-01-19_145729

3.6.椭圆

3.6.1.Lua

在on_update里面,判断触发地址和键值,若地址为LW6101,值为5,绘制椭圆,代码如下所示:

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
        local msg = ''
        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.ellipse] = function(control)--键值5
            draw_ellipse(225, 128, (225+180), (128+250), 0)--填充
            draw_ellipse(418, 163, (418+180), (128+180), 1)--不填充
        }        
    end,

    if switch[draw_type]
    then
        switch[draw_type](control)
    end
end

3.6.2.预览

运行预览,点击椭圆按钮,绘制1个填充,1个不填充的椭圆,设置画笔颜色,椭圆颜色随着改变,如下所示:

Video_2024-01-19_150242

Copyright ©Dacai all right reserved,powered by Gitbook该文件修订时间: 2026-02-10 11:34:53

results matching ""

    No results matching ""