ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

【CStackGUI 入门 01】把界面“画“出来:12 类基础控件与容器的相对坐标

【CStackGUI 入门 01】把界面“画“出来:12 类基础控件与容器的相对坐标 文章目录一、先说清楚它解决什么问题二、五步跑起来三、一屏总览12 类控件各管什么四、逐个控件它是什么、怎么用4.1 button最常用的那个4.2 显示类iconbutton / label / link4.3 switch / badge / tag / separator4.4 三种容器和相对坐标这件大事五、C 侧只有两件事绑定表 回调六、三个容易踩的地方本课全部踩过一遍七、这一课的验收标准八、常见问题 FAQ8.1 编译失败8.2 控件不显示8.3 事件不触发8.4 坐标错乱九、下一篇一、先说清楚它解决什么问题写给自己、给同事用的小工具读串口、批量处理文件、连设备看数据时最烦的常常不是业务逻辑而是界面MFC / Qt界面代码比业务还长改一个按钮的位置要重新编译、重新发版Python tkinter挺好写但要发给别人就得装解释器、装依赖套个网页体积、离线、串口权限都不顺。这个框架的取舍是环节做法界面用画布拖控件存成一个.cgui文件就是 JSON由运行时读取业务写 C只#include cstackgui.h不碰任何 Windows 头文件交付链成一个独立 exe一两 MB零依赖双击就跑于是有了两条最实在的好处改界面不用重新编译—— 挪个按钮、改句文案改完.cgui直接重跑 exe发人就是发一个 exe 旁边那个.cgui不用装任何东西。五篇地图每篇 一屏控件 一个主题都能单独看懂另计划一篇导读 一篇实战篇主题你会学到01本篇基础与容器按钮、标签、开关、徽章、三种容器02输入与选择输入框单行/多行/数值框、复选、单选、下拉、日期、月历03数值与指示滑块、进度条、圆环、仪表盘、状态灯、评分、分页04数据与日志标签页、树、表格、终端、图表、分隔条05命令与图形菜单、工具栏、画板、外形、图片、网页另有可选的两篇导读框架是什么、装什么、第一个 exe 怎么出来与实战篇照着仓库里的examples\notepad走一遍真实工具的结构菜单分发、脏标记、配置持久化。下面是这个框架的整体架构交付运行期设计期画布拖控件生成 .cgui 文件(JSON)运行时读取 .cgui渲染界面C 业务代码#include cstackgui.h回调函数独立 exe(一两 MB).cgui 文件二、五步跑起来前提只有一条装个MinGW-w64 gcc8 即可gcc --version能跑就行。不需要 Node、不需要 Visual Studio。:: ① 编译在仓库根目录 build-app.bat lesson01_basics :: ② 直接跑 examples\lesson01_basics\lesson01_basics.exe产物就在课自己的目录里结构很简单examples\lesson01_basics\ lesson01_basics.exe-双击就能跑界面文件就在旁边 lesson01_basics.cgui-界面用画布打开改改完不用重编译 main.c-业务你要读、要改的就是这个文件 lib\-运行时库副本③改一行看看用画布打开.cgui或直接文本编辑把text: 主按钮改成点我不用重新编译直接重跑 exe —— 按钮上的字就变了。这条是它最好用的地方。④自检不用开窗CI 里唯一能自动发现事件名写错的手段examples\lesson01_basics\lesson01_basics.exe --selftest examples\lesson01_basics\lesson01_basics.cgui输出末尾会给你一份体检报告-- 结果: 控件 30 个, 触发回调 10 次, 未登记 0 个, 事件不支持 0 个, 绑定出错 0 个 -- selftest OK这一课一共 30 个控件、10 个回调后面每讲一个控件都能在这两个数字里对上。三、一屏总览12 类控件各管什么这一课故意把搭界面最基础的那批一次摆齐一共 12 类控件.cgui里的类型一句话有事件吗按钮button点一下就是一次click✅图标按钮iconbutton只放一张图、不带文字✅标签label显示一段文字也能被程序改❌链接link蓝色下划线、可点✅开关switch开/关两态✅change徽章badge小圆片只放一段短文字❌标签片tag比徽章长一点的圆角片可点✅分割线separator一条横线只负责分组❌分组框group带标题的容器❌容器本身没有事件容器块box不带标题的容器❌卡片card贴边的卡片容器❌状态栏statusbar窗口底部一条用来报结果❌有事件吗这一列很关键不是所有控件都能挂回调 —— 标签、徽章、分割线、状态栏这些是纯显示件给它们绑事件运行时会在启动时警告、--selftest会返回 5。想知道某类控件支持哪些事件看docs\CGUI-FORMAT.md第 4 节的类型表。四、逐个控件它是什么、怎么用4.1button最常用的那个{id:btn_primary,type:button,rect:{x:120,y:16,w:104,h:32},text:主按钮,hint:最常用的控件点一下就是一次 click 事件}.cgui里挂上回调名events:{click:on_btn_primary_click}C 侧写一个同名的函数名字必须逐字相同原因见第五节/** brief 主按钮被点往状态栏写一句 */staticvoidon_btn_primary_click(cg_widget_t*self,cg_event_tev,void*user){cg_app_t*appcg_app_of(self);staticintn0;n1;cg_status_setf(cg_find(app,sb_main),0,主按钮被点了第 %d 次,n);}禁用态同样是一个字段但有个坑只有button/checkbox/radio/switch这四类皮肤真的画得出灰掉的样子其它控件写enabled: false之后长得和启用态一模一样拿它示范禁用只会让读者以为你写错了。{id:btn_disabled,type:button,text:已禁用,enabled:false,hint:enabled: false —— 点不动文案要写清为什么不能用}4.2 显示类iconbutton/label/link{id:icb_run,type:iconbutton,src:assets/icon.png,hint:只放一张图没有文字点击同样是 click 事件}{id:lab_hello,type:label,text:这是一段标签文字}{id:lnk_docs,type:link,text:点我试试链接,hint:蓝色下划线的可点文字要真跳转就在回调里调 cg_shell_open(url)}iconbutton的图用src指定相对.cgui的路径label一个事件都没有但程序可以随时改它的文字这是它最有用的地方cg_widget_set_textlink是看起来像链接的文字点击事件你要自己接 —— 想真的打开网址回调里一行cg_shell_open(https://www.example.com);/* 用系统默认浏览器打开 */4.3switch/badge/tag/separator{id:sw_notify,type:switch,hint:开/关两态勾选状态读作 checked不是 value}{id:bad_count,type:badge,text:12,hint:小圆片纯显示控件没有事件}{id:tg_demo,type:tag,text:标签片,hint:比徽章长一点的圆角片可以点}{id:sep_line,type:separator,hint:一条横线只负责分隔没有事件}开关的状态读checked而不是value这一点和滑块那种数值控件不一样intoncg_widget_checked(cg_find(app,sw_notify));/* 0 / 1 */4.4 三种容器和相对坐标这件大事容器group分组框 /box容器块 /card卡片存在的意义有两条视觉分组以及坐标隔离。{id:grp_form,type:group,rect:{x:16,y:232,w:344,h:148},text:group 分组框,children:[{id:lab_in_grp,type:label,rect:{x:12,y:28,w:300,h:22},text:容器里的控件用相对坐标相对分组框左上角},{id:btn_in_grp,type:button,rect:{x:16,y:60,w:104,h:32},text:组内按钮,hint:它的坐标 (16,60) 是相对分组框的不是相对窗口,events:{click:on_btn_in_grp_click}}]}这是本节唯一要记住的事children里的rect是相对容器左上角的。把整个分组框拖到别处里面的控件跟着走你不用改任何子坐标。什么时候用哪个要标题 边框的表达用group纯粹的版面切分用box要一块贴着边的面板用card。三个都是同一套容器机制选哪个主要看观感。五、C 侧只有两件事绑定表 回调完整骨架就这么点main.c里逐字可查#includecstackgui.h/* 业务代码只 include 这一个头 */staticconstcg_binding_tk_bindings[]{CG_BIND(on_btn_primary_click,on_btn_primary_click),/* 左.cgui 里写的名字右C 函数 *//* … 其余 9 个 */CG_BIND_END};intmain(intargc,char**argv){cg_app_desc_tdesc{0};desc.bindingsk_bindings;desc.cgui_pathlesson01_basics.cgui;desc.auto_locate_cgui1;/* 双击 exe 也能跑自动在 exe 旁边找 .cgui */if(argc1strcmp(argv[1],--selftest)0)returncg_app_selftest(desc);returncg_app_run(desc);}回调签名永远是同一个staticvoidf(cg_widget_t*self,cg_event_tev,void*user);self触发事件的控件不会为NULL拿它就能反查窗口cg_app_of(self)ev事件类型一个函数绑了多个事件时用来区分user业务数据挂载点默认NULL。为什么事件名写错不报编译错因为.cgui里存的是Function 名字符串运行时按名字在CG_BIND表里查函数指针 —— 这正是改界面不用重编译的代价。所以框架给了三道保险启动后汇总弹一次提示“这些事件不会触发”--selftest以非 0 退出码报出来CI 里唯一能自动发现它的手段画布「事件」页签的「代码」按钮能直接跳到对应函数。六、三个容易踩的地方本课全部踩过一遍错误的禁用示范只有button/checkbox/radio/switch有禁用视觉见 4.1。给显示件绑事件label/badge/separator/statusbar没有事件绑了不会崩但事件永远不会触发 启动时警告 —— 自查办法就是跑--selftest。容器坐标搞混写容器里的控件时脑子里把原点挪到容器左上角。如果发现控件跑到窗口左上角去了九成是把它当成了顶层控件或者反过来。七、这一课的验收标准:: 编译 自检应当 exit 0 build-app.bat lesson01_basics examples\lesson01_basics\lesson01_basics.exe --selftest examples\lesson01_basics\lesson01_basics.cgui :: 仓库级门禁改了 .cgui 字段或控件表时必跑 tools\check-format.bat自检输出的控件 30 个, 触发回调 10 次, 未登记 0 个, 事件不支持 0 个—— 最后两个 0 才是关键没有未登记的、没有绑错事件的。八、常见问题 FAQ这一课踩过的坑整理成一份可以直接照着查的清单。遇到问题先跑一遍--selftest它能帮你排除掉一大半事件名写错类的问题。8.1 编译失败现象build-app.bat报错exe 没生成。排查步骤确认gcc --version能跑且版本 ≥ 8。装的是 MinGW-w64不是别的 gcc 发行版确认在仓库根目录执行build-app.bat不是进到examples\lesson01_basics\里再跑看报错里第一个error而不是后面的note。最常见的是main.c里函数名和.cgui里的事件名对不上 —— 但编译期不会报这个它只会在运行期/自检时报见 8.3如果报cstackgui.h: No such file or directory说明lib\目录没被正确引用检查build-app.bat里的-I路径。解决按上面顺序逐条核对绝大多数是路径或目录问题。8.2 控件不显示现象exe 能跑但界面上少了某个控件或者整个窗口是空的。排查步骤先确认.cgui文件就在 exe旁边auto_locate_cgui 1时它自动找但别依赖它用画布打开.cgui看控件是不是被拖到窗口可视区域之外了rect的x/y是负数或超出窗口宽高检查控件是不是被别的控件盖住了—— 后画的控件会盖住先画的层级不对就看不到如果控件在容器里确认它的rect是相对容器的不是相对窗口见 8.4。解决把rect改回窗口范围内或调整控件在.cgui里的先后顺序。8.3 事件不触发现象点了按钮没反应或者启动时弹这些事件不会触发。排查步骤先跑--selftest看输出里未登记和事件不支持是不是 0未登记 0.cgui里写的事件名在CG_BIND表里找不到—— 检查main.c里CG_BIND(名字, 函数)的名字字符串是否和.cgui里逐字相同大小写、下划线都不能差事件不支持 0给纯显示件label/badge/separator/statusbar绑了事件 —— 这类控件没有事件绑了也不会触发确认回调函数签名是static void f(cg_widget_t *self, cg_event_t ev, void *user)参数不能少确认.cgui里events写的是click: on_btn_primary_click这种字符串不是函数指针。解决按--selftest的报错逐条改改完重跑自检直到两个 0。8.4 坐标错乱现象控件跑到窗口左上角去了或者容器里的控件位置不对。排查步骤先问自己这个控件在不在容器里在容器里 →rect是相对容器左上角的(0,0)是容器左上角不是窗口左上角不在容器里 →rect是相对窗口的。把容器拖到别处里面的控件跟着走 —— 如果没跟着走说明它被写成了顶层控件检查容器本身的rect是不是在窗口范围内容器跑出去了里面的控件自然也跟着跑。解决把容器里的控件坐标改成相对容器的值或者把误写成顶层控件的挪进children里。九、下一篇入门 02输入与选择一个表单要用到的输入控件 —— 输入框的三种形态单行 / 多行 /数值框、六种边框、输入方式档位整数/小数/字节/日期时间…、复选、单选、下拉、列表、日期、月历。入门 03数值与指示滑块拖一下进度条/圆环/仪表盘/标签全跟着变 —— 其中一个是一行 C 都不用写的控件绑定.cgui里填个bind就行。
返回列表