YStudio Y++

常见任务写法

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

按任务抄完整可运行片段;签名细节以各专题文档为准。入门先看 最小窗口程序、语言基础。

硬约束

  1. 控件名来自窗口 XML 的 名称;事件形参以该控件文档为准。
  2. 属性用 =,方法必须 ();逻辑用 真 / 假。
  3. 数组写 整数 arr[] / 文本 list[];循环计数变量须外部先声明。
  4. 类名写全:HTTP类、JSON类、绘制类、TCP类、WebSocket类、SQLite类。
  5. 多窗口:载入(窗名) / 关闭(窗名) 无引号。
  6. 网络回调用 &函数名 注册;形参以该类「事件」表为准,禁止自行删改。

1. 读控件、写控件

假定 XML 中有 标签1、文本框1、按钮1、组合框1、复选框1。

函数 主窗口.创建完毕() {
    标签1.标题 = "就绪"
    文本框1.文本 = ""
    组合框1.清空()
    组合框1.加入项目("选项A")
    组合框1.加入项目("选项B")
    组合框1.置当前索引(0)
    复选框1.选中 = 假
}

函数 按钮1.单击(整数 X, 整数 Y) {
    文本 t = 文本框1.文本
    整数 i = 组合框1.取当前索引()
    文本 项 = 组合框1.取项目文本(i)
    如果 (复选框1.选中) {
        标签1.标题 = t + " / " + 项
    } 否则 {
        标签1.标题 = "未勾选"
    }
}

对照:label · textbox · button · combobox · checkbox


2. 分支、循环、遍历数组

整数 i = 0
循环 (5, i) {
    输出(i)                    // 0…4
}

整数 n = 0
循环 (1, 10, 2, n) {
    输出(n)                    // 1,3,5,7,9
}

整数 k = 0
当 (k < 3) {
    k = k + 1
    输出(k)
}

整数 arr[] = [10, 20, 30]
整数 项 = 0
遍历 (项, arr) {
    输出(项)
}

文本 list[] = ["甲", "乙"]
文本 行 = ""
遍历 (行, list) {
    输出(行)
}

对照:basic-flow · basic-array · language §4.1

接收「整数数组 / 文本数组」返回值:

整数 索引[] = 列表框1.取选中索引()     // 元素为整数的数组
文本 名列表[] = 取进程列表()           // 以各命令签名为准

3. 读写文本文件

函数 按钮保存.单击(整数 X, 整数 Y) {
    文本 路径 = 合并路径(取程序目录(), "note.txt")
    如果 (写文件(路径, 文本框1.文本)) {
        信息框("已保存")
    } 否则 {
        信息框("保存失败")
    }
}

函数 按钮打开.单击(整数 X, 整数 Y) {
    文本 路径 = 合并路径(取程序目录(), "note.txt")
    如果 (文件存在(路径)) {
        文本框1.文本 = 读文件(路径)
    } 否则 {
        信息框("文件不存在")
    }
}

对照:basic-file。二进制用 读入文件 / 写出文件 等字节集命令。


4. HTTP + JSON

函数 按钮拉取.单击(整数 X, 整数 Y) {
    HTTP类 http
    http.置超时(15000)          // 毫秒
    文本 正文 = http.提交("GET", "https://example.com/api/info")
    如果 (http.取状态码() < 200 || http.取状态码() >= 300) {
        标签1.标题 = "请求失败:" + http.取错误()
        返回()
    }
    JSON类 j
    如果 (j.解析(正文) == 假) {
        标签1.标题 = "JSON 失败:" + j.取错误()
        返回()
    }
    标签1.标题 = j.取文本("message", "")
}

POST 带正文:

HTTP类 http
http.置超时(15000)
文本 体 = "{\"name\":\"Y++\"}"
文本 回 = http.提交("POST", "https://example.com/api", 体)
如果 (回 == "") {
    标签1.标题 = http.取错误()
}

对照:http · json

HTTP类 只做客户端(请求别人)。要本机「监听端口当服务端」用下面的 TCP / WebSocket。


5. 多窗口

函数 按钮打开工作台.单击(整数 X, 整数 Y) {
    载入(工作台)                 // 窗口名无引号
}

函数 按钮关闭登录.单击(整数 X, 整数 Y) {
    关闭(登录窗)
}

// 在「工作台」窗口的代码里访问本窗控件可直接写名称;
// 访问其它窗:工作台.标签1.标题 = "来自别处"

对照:多窗口设计


6. 列表框 / 菜单

函数 主窗口.创建完毕() {
    列表框1.清空()
    列表框1.加入项目("一行")
    列表框1.加入项目("二行")
    列表框1.置当前索引(0)

    菜单栏1.清空()
    菜单栏1.加入主菜单("文件")
    菜单栏1.加入子菜单(0, "打开")
    菜单栏1.加入分割线(0)
}

函数 列表框1.项被单击(整数 当前索引, 文本 项目) {
    标签1.标题 = 项目
}

函数 菜单栏1.项被单击(整数 索引, 文本 项目文本) {
    标签1.标题 = 项目文本
}

对照:listbox · menubar


7. 定时器

定时器类 t

函数 滴答() {
    输出("tick")
}

函数 主窗口.创建完毕() {
    整数 id = t.启动(1000, &滴答)   // 毫秒;返回定时器 ID
}

函数 按钮停.单击(整数 X, 整数 Y) {
    t.停止()                        // 省略 ID=停本对象全部;详见 timer-obj
}

对照:timer-obj。子程序指针写法见 callback。


8. 绘制类叠画(任意控件上)

绘制类 g

函数 按钮1.单击(整数 X, 整数 Y) {
    g.绑组件(按钮1)              // 组件名无引号
    g.置填充色("#332D7EF7")
    g.画矩形(4, 4, 40, 20)
    按钮1.刷新()
}

对照:painter。画布场景编辑见 canvas / yss/canvas。


9. 自定义类型(.yt)

源代码/点.yt:

点 {
    整数 x = 0,
    整数 y = 0
}

main.yc:

函数 主窗口.创建完毕() {
    点 p
    p.x = 10
    p.y = 20
    点 arr[] = []
    // 按 usertype 文档追加元素或字面量初始化
    标签1.标题 = 到文本(p.x) + "," + 到文本(p.y)
}

对照:usertype · examples/usertype


10. 给窗口换肤(YSS)

  1. 读 窗口/主窗口/主窗口.xml → 记下 名称、typeId(如 button、textbox)。
  2. 在 资源/主窗口.yss 写规则(属性键必须英文):
form {
    background-color: #1E1E1E;
}
button#确定 {
    background-color: #007ACC;
    color: #FFFFFF;
    border-radius: 4;
}
button#确定:hover {
    background-color: #1C97EA;
}
textbox {
    background-color: #252526;
    color: #E0E0E0;
    border-color: #3F3F46;
}
  1. F5:资源复制到 exe 旁,启动自动加载 主窗口.yss,一般不用手写 加载YSS()。
  2. 换肤 / 子目录主题:
函数 主窗口.创建完毕() {
    加载YSS(":/yss/主题.yss")
}
  1. 查键:总览 YSS.md → 该控件「YSS 样式」分文档(如 button)。
  2. 不要用 YSS 改布局坐标;表格格子配色用代码 API(见 datagrid / tablewidget)。

11. TCP 服务端回显(本机联调)

假定窗体有 标签1。TCP 不是控件事件:先写回调函数,再用 &函数名 注册,最后 启动/连接。

回调形参必须与文档一致(勿自行删参数)。

TCP类 srv
TCP类 cli

函数 服务进入(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口) {
    标签1.标题 = "接入 " + IP端口
}

函数 服务数据(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口, 文本 数据) {
    // 服务端回发必须带 连接ID
    srv.发送(连接ID, "回:" + 数据)
}

函数 服务离开(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口) {
    标签1.标题 = "离开 id=" + 到文本(连接ID)
}

函数 主窗口.创建完毕() {
    srv.客户进入(&服务进入)
    srv.数据到达(&服务数据)
    srv.客户离开(&服务离开)
    srv.置分包模式(0)                 // 0=原始流;教学明文可先用 0
    如果 (srv.启动(19000, "127.0.0.1") == 假) {
        标签1.标题 = "监听失败:" + srv.取错误()
    }
}

函数 按钮连.单击(整数 X, 整数 Y) {
    如果 (cli.连接_同步("127.0.0.1", 19000) == 假) {
        标签1.标题 = "连接失败:" + cli.取错误()
        返回()
    }
    如果 (cli.发送("你好") <= 0) {
        标签1.标题 = "发送失败"
        返回()
    }
    文本 r = cli.接收(256)
    标签1.标题 = "收到:" + r
    cli.断开()
}

对照:tcp · callback(&函数名)


12. WebSocket 服务端回显

WebSocket类 srv
WebSocket类 cli

函数 服务进入(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口) {
    标签1.标题 = "WS 接入 " + IP端口
}

函数 服务收到(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口, 文本 数据) {
    srv.发送(连接ID, "echo:" + 数据)   // 返回逻辑
}

函数 服务离开(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口, 整数 状态码, 文本 原因) {
    标签1.标题 = "WS 离开 code=" + 到文本(状态码)
}

函数 主窗口.创建完毕() {
    srv.置路径("/chat")
    srv.置允许来源("*")
    srv.客户进入(&服务进入)
    srv.数据到达(&服务收到)
    srv.客户离开(&服务离开)
    如果 (srv.启动(18765, "127.0.0.1") == 假) {
        标签1.标题 = "WS 启动失败:" + srv.取错误()
    }
}

函数 按钮连.单击(整数 X, 整数 Y) {
    cli.置超时(3000)
    如果 (cli.连接_同步("ws://127.0.0.1:18765/chat") == 假) {
        标签1.标题 = "WS 连接失败:" + cli.取错误()
        返回()
    }
    如果 (cli.发送("ping") == 假) {
        标签1.标题 = "发送失败"
        返回()
    }
    文本 r = cli.接收()
    标签1.标题 = r
    cli.关闭()
}

对照:websocket。UDP 监听见 udp;本机进程间通信见 pipe(创建服务端 / 连接,短名建议 ASCII,如 YppDesk)。


13. SQLite 建表、插入、查询

函数 主窗口.创建完毕() {
    SQLite类 db
    如果 (db.打开("data/demo.db") == 假) {
        标签1.标题 = db.取错误()
        返回()
    }
    // 旧版列定义文本亦可用(见 sqlite 文档)
    如果 (db.表是否存在("用户") == 假) {
        db.建表("用户", "id:主键,姓名:文本,年龄:整数")
    }
    db.插入("用户", "姓名,年龄", "张三,20")
    如果 (db.查询("用户", "", "姓名,年龄", "年龄 DESC", 10)) {
        当 (db.取下一行()) {
            文本 名 = db.取文本("姓名")
            文本 龄 = db.取文本("年龄")
            标签1.标题 = 名 + " / " + 龄
        }
    }
    db.关闭()
}

对照:sqlite · MySQL 见 mysql


14. 查文档的固定顺序

  1. 打开本窗 XML → 记下控件 名称、typeId。
  2. 打开对应 yss/*.md → 抄属性 / 方法 / 事件;要换肤再看该页「YSS 样式」与 YSS.md。
  3. 用到支持库 → 打开该库文档的方法/事件表;回调形参以事件说明为准。
  4. 语法拿不准 → language / basic-flow。
  5. 禁止在签名表外发明方法名或改事件形参。

易错对照

错误 正确
文本框1.内容 多数工程用 文本框1.文本(以 textbox 属性表为准)
按钮1.被单击() 无参 按钮1.单击(整数 X, 整数 Y)
HTTP http HTTP类 http
载入("工作台") 载入(工作台)
整数[] a 整数 a[]
遍历(整数 项, arr) 先 整数 项 = 0,再 遍历(项, arr)
YSS 写 背景色: #fff background-color: #FFFFFF;(英文键 + #RRGGBB)
button#确定:悬停 button#确定:hover
用 YSS 精细画数据表格每一格 外壳用 YSS;格子用 置区域背景色 等
http.置超时(15) 当秒 置超时 单位是毫秒:15000
函数 srv.数据到达(...) 当控件事件 TCP/WS:srv.数据到达(&回调),回调形参按文档
服务端 发送("hi") 不带连接ID 发送(连接ID, "hi")
TCP / WebSocket TCP类 / WebSocket类

相关

最小窗口程序 · YSS 样式 · 语言基础 · 流程控制 · TCP类 · WebSocket类 · 工程结构 · 窗口 XML