打开软件的“程序”页面,可以看到“刀路预览”“文件管理”“加工向导”三个页签。点击其中一个,下方就换成对应的内容。
这一篇就讲软件原来已有的这个功能。读完后,你应当能顺着页面找到脚本,并说清楚:点了哪里、哪个数发生变化、为什么显示这个页面、页面内容从哪个文件读进来。
不需要新增参数、按钮或页面,也不需要编译程序。下面的代码都是标准 env 中已有的写法。我们暂时只看三个子页面怎样切换,不展开文件管理操作和加工向导算法。
在主界面点击“程序”。它的下一行就是三个子页面的入口。先选择“刀路预览”:这个页签呈浅蓝色,下方左侧是刀路绘图区,右边是程序内容和 G/M 状态,再下面是加工文件列表。
点击截图可查看原图。
图 1 “程序 → 刀路预览”。示例文件为“圆形铣底.nc”:左侧从上方观察圆形刀路,右侧显示同一文件的程序内容,下方列出该文件。图中右侧第 10 行为蓝色选中行,左侧对应圆周呈红、紫相间的高亮。右上角红色状态标签显示“仿真”。本图只作离线预览,没有启动机床加工。
接着点击“文件管理”。这个页签变为浅蓝色,下方换成盘符和文件列表;右侧坐标、功能按钮以及底部功能键仍在原来的位置。
点击截图可查看原图。
图 2 从“程序”进入,在下一行选择“文件管理”。图中的目录为示例,你的文件目录可以不同。
再点击同一行的“加工向导”。亮色移到了“加工向导”,下方出现“割方形框”“割圆形框”“铣矩形底”“铣圆形底”等内容。
点击截图可查看原图。
图 3 点击“加工向导”后的页面。本篇只看页面怎样出现,不操作里面的“加载文件”或“执行”。图中的尺寸等数值是现有配置的显示值,不是本课要输入的加工参数。
观察这三张图时,只抓住两个变化:哪一个页签变亮,下面显示哪一块内容。 现有组态用同一个数,同时决定这两件事。
截图中的坐标和数值为示例,请以软件和机台的实际配置为准。
在宏程序里,常用一个变量记录当前进行到哪一步。这里采用相似的办法,用 #810 记录当前选择的子页面。
#810 的值 |
当前选择 | 应当显示的内容 |
|---|---|---|
0 |
刀路预览 | 刀路预览区域 |
1 |
文件管理 | 文件管理页面 |
2 |
加工向导 | 加工向导页面 |
因此,点击“文件管理”时,首先发生的就是:
#810=1
点击“加工向导”时,则是:
#810=2
这两个赋值都已经写在原有页签的设置中,不需要操作者手工输入。#810 的这套 0/1/2 分工,是标准组态给这三个页面作出的约定。
另外还有一个容易看错的写法:#810.permission。在本例中,它记录的是上面一行选了哪个大页面,例如“程序”为 0;而 #810 记录的是程序下面选了哪个子页面。它们是同一参数的不同字段,不能混着使用。这里的 permission 字段被组态用作大页面选择,并不表示登录身份。
从软件运行目录进入 env。本篇主要看以下文件:
| 文件 | 本篇要看什么 |
|---|---|
env/dmec-app-black.ui |
最外层主界面;其中装入标准主界面内容 |
env/maininterface/maininterface.ui |
“程序”入口、三个页签,以及各自内容的显示位置 |
env/file/filepage |
点击“文件管理”时运行的脚本 |
env/file/file.ui |
文件管理页面的具体布局 |
env/program/advancedpage |
点击“加工向导”时运行的脚本 |
env/program/advanced.ui |
加工向导页面的具体布局 |
env/main |
启动时把选页值和首次打开标志准备好 |
.ui 文件描述页面上的控件、布局和设置;filepage、advancedpage 这样的无扩展名文件是组态脚本,可以用文本编辑器阅读。
如果用 Qt Designer 查看 maininterface.ui,在对象列表中找到下列名字。objectName 是控件在文件里的名字,方便脚本准确找到它;屏幕上显示的中文名称可以与它不同。
| 屏幕上的位置 | 文件里的名字(objectName) |
|---|---|
| “程序”入口 | label_39 |
| “刀路预览”页签 | label_44 |
| “文件管理”页签 | label_45 |
| “加工向导”页签 | label_46 |
| 刀路预览的内容区域 | frame_17 |
| 文件管理的内容区域 | fileFrame |
| 加工向导的内容区域 | advancedFrame |
这些页签在 UI 文件中使用的是标签控件 QLabel,组态给它们设置了点击动作,所以使用起来像按钮。下方三个内容区域使用 QFrame,可以把它理解为页面中预留的一块放内容的位置。
接下来主要看控件的 accessibleDescription 属性。这个英文名字是编辑器里的真实属性名;本系统把“显示什么、点击时做什么、什么时候显示”等组态写在这里。阅读 XML 文件时看到的 <、> 等属于 XML 转义;下面代码块按属性编辑器实际显示的文字书写。
找到 label_45,它的 accessibleDescription 原文是:
-T(#1100itemtitle6)
-A:(clickedEvent:/env/file/filepage[0](#810=1))
-C1(#810==1)
-C0(1)
-C(#929item5==1)
-V2
-D
先看第二行,不必一次记住所有写法:
-A:(clickedEvent:/env/file/filepage[0](#810=1))
它把三件事放在同一个设置里:
| 这一段 | 在本例中的意思 |
|---|---|
clickedEvent |
点击这个页签时执行 |
(#810=1) |
先把当前子页面记为文件管理 |
/env/file/filepage[0] |
然后调用 env/file/filepage;[0] 选择调用脚本的通道 |
这里的 /env/... 按软件工作目录查找。[0] 不是“第 0 页”:本次选择的是文件管理,也就是 #810=1。先把赋值与文件路径看清,就能从界面一路找到要读的脚本。
其余几行分别负责文字、亮色和入口是否出现:
| 原有写法 | 做什么 |
|---|---|
-T(#1100itemtitle6) |
从 #1100.itemtitle[6] 取得页签文字。中文语言包写入“文件管理” |
-C1(#810==1) |
当 #810 为 1 时,采用 1 号外观,即图中的选中亮色 |
-C0(1) |
不满足前面的选中条件时,采用 0 号普通外观 |
-C(#929item5==1)、-V2 |
用第 3 个条件决定这个入口是否显示;文件管理功能开关为 1 时显示 |
-D |
在运行中持续检查并更新这个控件,让文字和状态跟上参数变化 |
-V2 中的 2 是条件的编号,从 0 开始数:上面三条 -C… 依次为第 0、1、2 条。它也不是页码。条件式在前、显示设置引用哪一条在后,两者要一起读。
亮色本身不写在脚本中。三个页签共同所在的区域 frame_16 已经定义了 0 号和 1 号外观,页签只要说明“什么时候选哪一种”即可。
在同一个 maininterface.ui 中找到 fileFrame。它的设置是:
-T(811)
-C(#810==1)
-V0
-D
这次先看后三行。这里只有一条条件,所以它的编号为 0:
-C(#810==1)
-V0
-D
意思是:检查 #810==1;条件成立就显示这个区域,不成立就隐藏;运行中继续更新。
另外两个内容区域分别检查 #810==0 和 #810==2。因此正常切换只要改一个 #810,就能让一块内容显示,另外两块隐藏。
| 点击后 | 页签为什么变亮 | 内容为什么出现 |
|---|---|---|
#810=0 |
刀路预览的 -C1(#810==0) 成立 |
frame_17 的显示条件成立 |
#810=1 |
文件管理的 -C1(#810==1) 成立 |
fileFrame 的显示条件成立 |
#810=2 |
加工向导的 -C1(#810==2) 成立 |
advancedFrame 的显示条件成立 |
页签和内容区域各有自己的设置,但都检查同一个选页值。 这就是两者能保持一致的原因。这里说的是更新后的对应关系,不承诺每个绘制动作在同一瞬间完成。
切走时,普通的显示/隐藏不会重新读取 UI 文件。那么,“文件管理”页面第一次是怎样放进 fileFrame 的?这要继续看点击时调用的脚本。
filepage 的七行读明白env/file/filepage 的完整有效内容如下:
widgetFunc["disk","","",803]
IF#811.version==1GOTO1
#811.version=1
widgetFunc["dir",#802,"",802]
#811.itemdesc[0]="/env/file/file.ui"
widgetFunc["QFrame","fileFrame","refresh",""]
N1
如果你熟悉 IF/GOTO,先从第二行判断读起:以前准备过这个页面,就直接跳到 N1;否则完成一次准备。
#811.version 在启动时已经被设为 0。所以第一次不会跳到 N1,会继续往下执行。
| 顺序 | 代码 | 本例中的作用 |
|---|---|---|
| 1 | widgetFunc["disk","","",803] |
把可用盘符的信息放入 #803,供左侧盘符列表使用 |
| 2 | IF#811.version==1GOTO1 |
判断是否已经做过首次准备 |
| 3 | #811.version=1 |
作一个“已经准备过”的标记 |
| 4 | widgetFunc["dir",#802,"",802] |
读取 #802 指定目录的内容,填入 #802 的文件列表数据 |
| 5 | #811.itemdesc[0]="/env/file/file.ui" |
记下这个区域要装入哪一个 UI 文件 |
| 6 | widgetFunc["QFrame","fileFrame","refresh",""] |
找到名为 fileFrame 的区域,按它的设置重新装入内容 |
| 7 | N1 |
前面跳转所用的标号,随后文件结束 |
widgetFunc[...] 是组态调用已有界面功能的写法。这里只用到了列盘符、列目录和装入页面三个功能;不必先把它的全部命令学完。
把以下三处接起来看:
fileFrame 的设置: -T(811)
脚本写入文件名: #811.itemdesc[0]="/env/file/file.ui"
脚本要求装入: widgetFunc["QFrame","fileFrame","refresh",""]
-T(811) 告诉这个区域“到 811 号参数里找内容说明”;该参数的 .itemdesc[0] 提供 UI 路径;refresh 才要求软件按这个说明装入页面。标准配置已经为 #811 准备了所需的子项。
注意,refresh 最后的 "" 是空字符串,文件路径写在前一行的 .itemdesc[0] 中。不要看到四个参数,就凭感觉把第四项当作 UI 文件名。
同样,不要把页签的 -T(#1100itemtitle6) 与区域的 -T(811) 混为一谈:前者给标签提供要显示的文字,后者给 QFrame 指定内容说明参数。要结合控件种类阅读。
此时 #811.version 已经是 1。脚本仍然先更新盘符,然后在第二行直接跳到 N1,不再重复执行目录首次读取、写 UI 路径和 refresh。
这也解释了为什么这个标志有用:页面切换负责让已有内容出现;首次准备负责把内容放进去。 每次切换都重新装入,会重新建立页面控件,不是现有组态的做法。
这里的 .version 是标准组态借用来保存标志的字段,不是软件版本号。现有脚本在装入 UI 之前就把它设成 1,所以这个值不能证明文件一定装入成功。如果文件丢失或名字写错,应继续查路径和文件,不能只看标志。
“加工向导”的点击设置是:
-A:(clickedEvent:/env/program/advancedpage[0](#810=2))
它先选择第 2 页,再运行 advancedpage。这个脚本开头四行是:
IF#812.version==1GOTO1
#812.version=1
#812.itemdesc[0]="/env/program/advanced.ui"
widgetFunc["QFrame","advancedFrame","refresh",""]
这是原文件的开头节选,后面还有向导自身的准备工作以及 N1,不能把这四行当作完整替换文件。
与文件管理对照,就能看出共用的方法:
| 要决定什么 | 文件管理 | 加工向导 |
|---|---|---|
| 选择哪一页 | #810=1 |
#810=2 |
| 放在哪个区域 | fileFrame |
advancedFrame |
| 到哪个参数找 UI 说明 | -T(811) |
-T(812) |
| UI 文件名放哪里 | #811.itemdesc[0] |
#812.itemdesc[0] |
| 用什么记住已经准备过 | #811.version |
#812.version |
加工向导内部还用 #812 的数值选择向导类别。不要因为同样看到 812,就把它当成这里的三子页选择;本篇三页始终由 #810 决定。
“刀路预览”的点击设置是:
-A:(clickedEvent:/env/null[1](#810=0))
env/null 是现有空脚本。这一项主要利用点击时的赋值,把 #810 改回 0。预览内容本来就在 maininterface.ui 中的 frame_17,所以不用像前两页那样,在首次点击时再读一个独立 UI 文件。
[1] 仍表示调用脚本的通道,并不表示选第 1 页。
在 env/main 中,可以找到这些原有赋值,下面按用途摘出:
#810.permission=0
#810=0
#811.version=0
#811.itemdesc[0]=""
#812.version=0
#812.itemdesc[0]=""
前两行选择“程序 → 刀路预览”。后面分别清掉文件页和向导页的首次准备标志、UI 文件路径。
这样,刚打开主界面时先显示预览;第一次点入文件管理或加工向导,才由它们自己的脚本填入路径并装入内容。只把页面隐藏起来,并不等于阻止软件在建立主界面时读取已经填好的 UI 路径,因此这里也会清空路径。
已经打开软件后,从“程序”切到别的大页面,再回到“程序”,情况不同:“程序”入口调用的 env/programpage 没有把 #810 清零。因此,在没有其他脚本改变选页值的情况下,可以保留之前选择的子页。切换语言、载入或恢复参数等流程另外有复位处理,不能把一次切页保留状态理解为永久记忆。
现在回看“点击文件管理”这个动作,可以按下面的顺序讲给别人听:
maininterface.ui 中,label_45 是“文件管理”入口。#810=1,随后运行 env/file/filepage。#810==1,这个页签使用亮色,fileFrame 被显示,另外两块内容被隐藏。#811.version 还不是 1,脚本写入 UI 路径,并让 fileFrame 装入 file.ui。设计这种页面时,现有组态实际解决了五个问题:用哪个数选页;点击时怎样改这个数;哪个区域显示;内容从哪个文件装入;什么时候需要重新准备。 这五件事合在一起,才是完整的三子页设计。
只切换页签即可,不需要运行加工程序,也不需要更改文件。
| 操作 | 观察什么 |
|---|---|
| 进入“程序”,点击“文件管理” | “文件管理”变亮,出现盘符和文件列表 |
| 点击“加工向导” | “加工向导”变亮,出现向导类别、尺寸输入和 MDI 区域 |
| 点击“刀路预览” | 亮色和内容一起返回预览 |
| 再次点击“文件管理” | 回到文件页;结合 IF/GOTO 理解这次为什么跳过首次准备 |
页面是否重新建立,不能仅凭肉眼判断。读者先通过上述操作核对显示效果,再对照脚本中的判断理解第一次与后续进入的区别。
| 现象或容易产生的误解 | 对照哪里 |
|---|---|
| 找不到“文件管理”入口 | 看 label_45 的 #929.item[5] 条件;入口受这个现有功能开关控制 |
| 页签亮了,下方却不是对应内容 | 分别检查页签和内容区域是否都判断同一个 #810 值 |
| 文件页为空 | 查 fileFrame 的 -T(811)、#811.itemdesc[0]、UI 文件是否存在、refresh 中的名字是否为 fileFrame |
看到 .version=1 就认为加载成功 |
这个值由脚本提前设置,不能替代对文件与实际页面的检查 |
把 [0]、-V2 当成页码 |
本例页码在 #810;另外两个数字分别属于脚本通道和条件编号 |
以为每次切页都要 refresh |
普通切页使用显示条件;原设计只在需要建立内容时执行 refresh |
现在,你可以把日常使用的三次点击,逐一对应到参数、页面设置和脚本。