YStudio Y++

画布控件

Y++ / YStudio 开发文档 · 一点滴

工具箱组件 画布(设计器类型名:画布;支持库:画布类)。
用于在窗口内做可交互的 2D 绘图:图形编辑、手绘笔迹、像素涂鸦、HUD 叠层、导出图片等。

配套样式说明见 yss/canvas.md。任意控件/窗口即时叠画见支持库 绘制类(与本页「画布类」不同:画布类管场景图元与像素层;绘制类可绑画布/组件/窗口做 QPainter 式叠画)。

硬约束

  1. 控件名来自窗口 XML,调用写 画布1.添加矩形(...)(方法必须带括号)。
  2. 鼠标事件坐标是控件坐标;添加* / 路径点用场景坐标(先 控件到场景X/Y)。
  3. 即时 API(画线/画矩形 等)仅在 绘制 事件内有效;跨事件保留叠画请用 绘制类。
  4. 添加* 失败返回图形 ID 0;颜色文本 #AARRGGBB / #RRGGBB。

1. 三种绘制层(先选对层)

从下到上每帧合成顺序为:

  1. 控件背景(设计器背景色等)
  2. 像素层(可选):整幅位图,适合涂鸦、贴图底图
  3. 场景层:带稳定 图形ID 的矢量/文本/图片节点,可点选、拖动、组合、持久化
  4. 即时层:只在 绘制 事件里临时画一帧,帧末清空,不进场景、不可点选 - 推荐用独立对象 绘制类(变换/裁剪/线型);画布上的 画线/画矩形 等即时 API 在绘制帧内已走同一路径
需求 用哪一层 典型 API
可点选的矩形、连线、图元 场景 添加矩形 / 添加直线 / …
鼠标拖出自由曲线并保留 场景路径 开始路径 → 线到 → 结束路径
十字准星、临时辅助线、帧率文字 即时 绘制类 或仅在 绘制 里 画线 / 画文本
位图涂抹、导入照片当底 像素 锁定像素 / 置像素 / 从字节集载入
保存当前画面给人看 导出 导出PNG / 到字节集
保存可再编辑的工程内容 场景文本 导出场景 / 导入场景

颜色统一用文本:#AARRGGBB 或 #RRGGBB(如 "#FFFF0000" 不透明红,"#4080FF80" 半透明蓝)。


2. 坐标系(极易写错)

画布上有两套坐标,都不是窗口客户区绝对坐标:

名称 原点 用途
控件坐标 画布控件左上角 鼠标事件 X/Y、取命中、框选、取/置像素
场景坐标 内容坐标系(已含视图平移与缩放) 添加*、置位置、路径点、移动选中

转换(传入的一对坐标是「点」的两个分量):

小数 sx = 画布1.控件到场景X(控件x, 控件y)
小数 sy = 画布1.控件到场景Y(控件x, 控件y)
小数 cx = 画布1.场景到控件X(场景x, 场景y)
小数 cy = 画布1.场景到控件Y(场景x, 场景y)

规则: 鼠标事件里先转场景再写入场景 API;取命中(X, Y) 直接用事件里的控件坐标。

视图:

  • 中键拖:平移(属性「允许平移」)
  • Ctrl+滚轮:缩放(属性「允许缩放」;「最小缩放」「最大缩放」为百分比,如 25 表示 0.25)
  • 代码:置视图(平移X, 平移Y, 缩放) / 复位视图() / 取平移X / 取平移Y / 取视图缩放
  • 视图变化会触发事件 视图改变
  • 选中集合变化会触发事件 选中改变(可用 取选中数 / 取选中列表)

3. 编辑模式与默认鼠标行为

画布1.置编辑模式(1)   // 1=选择+拖动(默认);0=关闭内置拖动(更适合纯手绘脚本)

当模式为 1 时(需先点击画布取得焦点):

操作 效果
左键点在图形上 选中;可拖动;单选显示缩放/旋转手柄
Ctrl+点图形 追加或取消该项选中
Shift+拖空白 框选;再按 Ctrl 为追加框选
空白处左键(无 Shift) 不强制选中;脚本可在此手绘
Delete / Backspace 删除选中
方向键 微调 1 场景单位;Ctrl+方向键为 10
Ctrl+C / X / V / D / A 复制 / 剪切 / 粘贴 / 克隆 / 全选

拖动时默认 吸附 其它图形边/中线;可用 置吸附 / 置网格 调整。


4. 场景图形:创建与改属性

所有 添加* 返回 整数图形ID(失败为 0)。之后用 ID 改外观与位姿。

4.1 创建(场景坐标;返回整数图形 ID,失败 0)

方法 签名 返回
添加直线 整数 画布.添加直线(小数 x1, 小数 y1, 小数 x2, 小数 y2) 整数
添加矩形 整数 画布.添加矩形(小数 x, 小数 y, 小数 宽, 小数 高) 整数
添加椭圆 整数 画布.添加椭圆(小数 x, 小数 y, 小数 宽, 小数 高) 整数
添加多边形 整数 画布.添加多边形(文本 点列) 整数
添加文本 整数 画布.添加文本(小数 x, 小数 y, 文本 内容) 整数
添加图片 整数 画布.添加图片(小数 x, 小数 y, 小数 宽, 小数 高, 文本 路径) 整数
开始路径 整数 画布.开始路径(小数 x, 小数 y) 整数
线到 逻辑 画布.线到(小数 x, 小数 y) 逻辑
曲线到 逻辑 画布.曲线到(小数 c1x, c1y, c2x, c2y, x, y) 逻辑
关闭路径 逻辑 画布.关闭路径() 逻辑
结束路径 整数 画布.结束路径() 整数
删除 逻辑 画布.删除(整数 图形ID) 逻辑
清空 无 画布.清空() 无
取数量 整数 画布.取数量() 整数
是否存在 逻辑 画布.是否存在(整数 图形ID) 逻辑
取图形列表 文本 画布.取图形列表() 文本

多边形示例:

整数 id = 画布1.添加多边形("0,0;100,0;50,80")
画布1.置填充色(id, "#4080FF80")
画布1.置描边色(id, "#FFFFFFFF")
画布1.置线宽(id, 2)

路径手绘(与选择模式共存时:先判断未命中图形再起笔):

逻辑 g_画中 = 假

函数 画布1.鼠标按下(整数 X, 整数 Y, 逻辑 按下) {
    如果 (画布1.取命中(X, Y) > 0) { 返回 }
    小数 sx = 画布1.控件到场景X(X, Y)
    小数 sy = 画布1.控件到场景Y(X, Y)
    整数 id = 画布1.开始路径(sx, sy)
    画布1.置描边色(id, "#FFFFEE88")
    画布1.置线宽(id, 2)
    g_画中 = 真
}

函数 画布1.鼠标移动(整数 X, 整数 Y, 逻辑 按下) {
    如果 (g_画中 && 按下) {
        画布1.线到(画布1.控件到场景X(X, Y), 画布1.控件到场景Y(X, Y))
    }
}

函数 画布1.鼠标抬起(整数 X, 整数 Y, 逻辑 按下) {
    如果 (g_画中) {
        画布1.结束路径()
        g_画中 = 假
    }
}

4.2 外观与变换(均带图形 ID)

方法 签名 返回 说明
置填充色 无 置填充色(整数 ID, 文本 颜色) 无
取填充色 文本 取填充色(整数 ID) 文本
置描边色 无 置描边色(整数 ID, 文本 颜色) 无
取描边色 文本 取描边色(整数 ID) 文本
置线宽 无 置线宽(整数 ID, 小数 宽) 无
取线宽 小数 取线宽(整数 ID) 小数
置位置 无 置位置(整数 ID, 小数 x, 小数 y) 无
取位置X 小数 取位置X(整数 ID) 小数
取位置Y 小数 取位置Y(整数 ID) 小数
置尺寸 无 置尺寸(整数 ID, 小数 宽, 小数 高) 无
取宽度 小数 取宽度(整数 ID) 小数
取高度 小数 取高度(整数 ID) 小数
置旋转 无 置旋转(整数 ID, 小数 角度) 无 度
取旋转 小数 取旋转(整数 ID) 小数
置缩放 无 置缩放(整数 ID, 小数 sx, 小数 sy) 无
取缩放X 小数 取缩放X(整数 ID) 小数
取缩放Y 小数 取缩放Y(整数 ID) 小数
置可见 无 置可见(整数 ID, 逻辑 可见) 无
取可见 逻辑 取可见(整数 ID) 逻辑
置锁定 无 置锁定(整数 ID, 逻辑 锁定) 无
取锁定 逻辑 取锁定(整数 ID) 逻辑
置Z序 无 置Z序(整数 ID, 整数 z) 无 越大越靠上
取Z序 整数 取Z序(整数 ID) 整数
置标签 无 置标签(整数 ID, 文本 标签) 无
取标签 文本 取标签(整数 ID) 文本

5. 选中、组合、对齐、剪贴板、层级

方法 签名 返回 说明
选中 无 选中(整数 图形ID, [逻辑 追加=假]) 无
取消选中 无 取消选中(整数 图形ID) 无
清空选中 无 清空选中() 无
全选 无 全选() 无
反选 无 反选() 无
是否选中 逻辑 是否选中(整数 图形ID) 逻辑
取选中数 整数 取选中数() 整数
取选中 整数 取选中(整数 索引) 整数 从 0
取选中列表 文本 取选中列表() 文本
置编辑模式 无 置编辑模式(整数 模式) 无 0关内置拖动 · 1选择+拖动(默认)
取编辑模式 整数 取编辑模式() 整数
组合 整数 组合() 整数 ≥2 选中;返回组 ID
取消组合 逻辑 取消组合([整数 组ID=0]) 逻辑
取父级 整数 取父级(整数 图形ID) 整数
是否组合 逻辑 是否组合(整数 图形ID) 逻辑
移动选中 无 移动选中(小数 dx, 小数 dy) 无 场景位移
框选 整数 框选(小数 x1, y1, x2, y2, [逻辑 追加=假]) 整数 控件坐标;返回新选中数
水平翻转 无 水平翻转() 无
垂直翻转 无 垂直翻转() 无
置吸附 无 置吸附(逻辑) 无
取吸附 逻辑 取吸附() 逻辑
置吸附容差 无 置吸附容差(小数) 无 屏幕像素
取吸附容差 小数 取吸附容差() 小数
置网格 无 置网格(小数) 无 场景单位;0=关
取网格 小数 取网格() 小数
对齐左 无 对齐左() 无
对齐右 无 对齐右() 无
对齐顶 无 对齐顶() 无
对齐底 无 对齐底() 无
水平居中 无 水平居中() 无
垂直居中 无 垂直居中() 无
水平分布 无 水平分布() 无 至少 3 个选中
垂直分布 无 垂直分布() 无 至少 3 个选中
删除选中 整数 删除选中() 整数
克隆选中 整数 克隆选中() 整数
复制选中 整数 复制选中() 整数
剪切选中 整数 剪切选中() 整数
粘贴 整数 粘贴() 整数
置顶 无 置顶() 无
置底 无 置底() 无
上移一层 无 上移一层() 无
下移一层 无 下移一层() 无
导出场景 文本 导出场景() 文本 YCANVAS\|1 开头
导入场景 整数 导入场景(文本 数据, [逻辑 清空=真]) 整数 导入项数
画布1.选中(id)
画布1.选中(id2, 真)
整数 n = 画布1.框选(0, 0, 200, 150)
画布1.移动选中(10, 0)
整数 g = 画布1.组合()

6. 即时层(仅 绘制 事件)

画布内置即时 API(坐标为场景坐标):

方法 签名 返回
置笔触 无 画布.置笔触(文本 颜色, 小数 线宽) 无
置填充 无 画布.置填充(文本 颜色) 无
画线 无 画布.画线(小数 x1, 小数 y1, 小数 x2, 小数 y2) 无
画矩形 无 画矩形(小数 x, 小数 y, 小数 宽, 小数 高) 无
画椭圆 无 画椭圆(小数 x, 小数 y, 小数 宽, 小数 高) 无
画文本 无 画布.画文本(小数 x, 小数 y, 文本 内容) 无

勿在其它事件里调用上述即时 API。跨事件/绑任意组件叠画请用 绘制类:绘制类 g → g.绑画布(画布1) 或 g.绑组件(按钮1)。

函数 画布1.绘制() {
    画布1.置笔触("#FFFFCC00", 1)
    画布1.画线(0, 0, 50, 50)
    画布1.置填充("#40FFFFFF")
    画布1.画矩形(10, 10, 40, 30)
    画布1.画椭圆(60, 10, 40, 30)
    画布1.画文本(5, 5, "提示")
}

7. 像素层与导出画面

方法 签名 返回 说明
锁定像素 逻辑 锁定像素() 逻辑
解锁像素 逻辑 解锁像素() 逻辑
清空像素 逻辑 清空像素() 逻辑
取像素宽 整数 取像素宽() 整数 未锁定时为 0
取像素高 整数 取像素高() 整数 未锁定时为 0
取像素 文本 画布.取像素(小数 x, 小数 y) 文本 控件坐标
置像素 逻辑 画布.置像素(小数 x, 小数 y, 文本 颜色) 逻辑
导出PNG 逻辑 画布.导出PNG(文本 路径) 逻辑 当前视图合成图
到字节集 字节集 画布.到字节集() 字节集 PNG
从字节集载入 逻辑 画布.从字节集载入(字节集 数据) 逻辑 替换像素缓冲

8. 场景持久化

文本 s = 画布1.导出场景()
到文件(取临时目录() + "scene.txt", s)      // 按你项目里的文件 API 书写

文本 s2 = 到文本(读入文件(...))            // 读回文本
整数 n = 画布1.导入场景(s2, 真)            // 真=先清空再导入;返回导入项数

导出场景 得到以 YCANVAS|1 开头的文本,含图形种类、位置、样式、组合关系、多边形点与路径点等,可供再次 导入场景 恢复可编辑内容。
若只要给人看的截图,用 导出PNG,不要用场景文本。


9. 事件

事件 参数 何时
绘制 无 每帧;写即时层
图形单击 整数 图形ID 点中场景图形
图形双击 整数 图形ID 双击图形
视图改变 无 平移/缩放变化后
选中改变 无 场景选中集合变化;可用 取选中数 / 取选中列表
鼠标按下 整数 X, 整数 Y, 逻辑 按下 控件坐标
鼠标移动 整数 X, 整数 Y, 逻辑 按下 控件坐标
鼠标抬起 整数 X, 整数 Y, 逻辑 按下 控件坐标
函数 画布1.选中改变() {
    输出("选中数=", 画布1.取选中数())
}

函数 画布1.图形单击(整数 图形ID) {
    输出("点中", 图形ID)
}

10. 设计器属性(画布专用)

面板标题 含义 语言读写
抗锯齿 绘制是否抗锯齿 画布1.抗锯齿
允许平移 是否允许中键拖视图 画布1.允许平移
允许缩放 是否允许 Ctrl+滚轮缩放 画布1.允许缩放
最小缩放 / 最大缩放 缩放范围(百分比整数,25=0.25 倍) 画布1.最小缩放 / 最大缩放

另有通用:背景色、边框、停靠等(语言侧亦可读写 背景色 / 显示边框 / 边框大小 / 边框颜色)。


11. 按需求对照写法(速查)

用户需求 建议写法
流程图/框图可拖可组合 场景 添加矩形+添加直线;模式 1;组合/对齐*
签字板/随手画 模式 1 + 空白处路径手绘;或模式 0 专心手绘
游戏 HUD / 准星 仅 绘制 里即时绘制
像素画板 锁定像素+置像素;可再叠场景
打开图片当底图 从字节集载入 或 添加图片
保存作品给人看 导出PNG
保存工程可再编辑 导出场景 / 导入场景
多选批量移动 框选 或 Ctrl 点选后 移动选中
对齐一排按钮图元 多选后 对齐顶+水平分布
读图元当前样式/位姿 取填充色 / 取位置X / 取旋转 等

12. 完整方法一览(画布类)

场景结构: 清空 添加直线 添加矩形 添加椭圆 添加多边形 添加文本 添加图片 开始路径 线到 曲线到 关闭路径 结束路径 删除 取数量 是否存在 取图形列表

外观变换: 置填充色 置描边色 置线宽 置位置 置尺寸 置旋转 置缩放 置可见 置锁定 置Z序 置标签
取填充色 取描边色 取线宽 取位置X 取位置Y 取宽度 取高度 取旋转 取缩放X 取缩放Y 取可见 取锁定 取Z序 取标签

坐标视图: 取命中 控件到场景X/Y 场景到控件X/Y 置视图 复位视图 取平移X 取平移Y 取视图缩放

即时: 置笔触 置填充 画线 画矩形 画椭圆 画文本

像素导出: 锁定像素 解锁像素 清空像素 取像素宽/高 取/置像素 导出PNG 到字节集 从字节集载入

选区编辑: 选中 取消选中 清空选中 是否选中 取选中数 取选中 取选中列表 置/取编辑模式 组合 取消组合 取父级 是否组合 移动选中 全选 反选 框选 水平/垂直翻转

吸附对齐: 置/取吸附 置/取吸附容差 置/取网格 对齐左/右/顶/底 水平/垂直居中 水平/垂直分布

剪贴板层级: 删除选中 克隆选中 复制选中 剪切选中 粘贴 置顶 置底 上移一层 下移一层

场景文本: 导出场景 导入场景