文件管理中的程序,是怎样选取和显示的

阅读目录 · English

本篇继续读标准组态已有的设计。我们不增加按钮,也不另做文件管理器,就从“程序 → 文件管理”选一份现有 NC 程序,沿着界面和脚本看清:目录从哪里来,单击记住什么,按“选取”以后又改了什么。

1.先在原有页面上看一遍

图1:标准中文文件管理页面,当前目录为programs,右下角是选取按钮

点击截图可查看原图。

图 1 点击“程序”下的“文件管理”。本例目录为 programs,里面放着已有的 圆形铣底.nc。底部“过滤器”显示 *.nc *.txt *.tap *.cnc。右上角状态是“仿真”。

先认清下面几处:

页面位置 本例要看什么
左侧“盘符” 选择在哪个磁盘浏览
中间文件表 “名称、大小、类型、修改日期”;文件和目录都可能在表内
下方“书签” 记住常用目录,不是加工程序列表
底部“文件路径” 当前浏览的目录
底部“文件名” 最近单击的文件名称
底部“过滤器” 当前要列出的文件类型
右下角“选取” 把表格中选中的行交给加工列表

单击文件表中的 圆形铣底.nc,先不要按“选取”。

图2:单击圆形铣底.nc后,原生文件管理区底部的文件名已填写

点击截图可查看原图。

图 2 这是原生文件管理区域的截图。“文件名”现在是 圆形铣底.nc,文件表仍然显示当前目录。此时只是记住刚才点了哪个文件;本例的当前加工文件仍为空。

再按右下角 “选取”。页面回到“刀路预览”,程序文字区出现刚才那份程序:

图3:选取后原生程序文字区显示圆形铣底.nc及其G代码

点击截图可查看原图。

图 3 这里只截取文件标题和程序文字区。首行是 G90G0Z20.000,第二行是 M3S12000。它们是文件内容;显示这些文字不表示已经执行主轴或轴运动。

下面的加工列表同时出现一行:

图4:原生加工列表出现圆形铣底.nc,起始行0、结束行-1、加工数量0/1、状态就绪

点击截图可查看原图。

图 4 本例从空加工组开始,显示“起始行 0、结束行 -1”,各偏移和旋转角度为 0.000,“加工数量”为 0/1,“加工状态”为“就绪”。这些是本次实际数据,不能据此认为每次重选程序都会清空旧偏移。

截图采用标准界面。坐标、文件名和参数数值为讲解示例,请以实际配置为准。

2.先找这几个文件和参数

路径均相对于软件运行目录。

文件 在本例中的工作
env/maininterface/maininterface.ui 放置“文件管理”入口、子页位置、程序文字区和加工列表
env/file/filepage 首次进入时读目录、装入文件管理页面
env/file/file.ui 定义文件表、路径框、筛选框和按钮
env/file/enterDir 单击目录时进入目录;单击文件时记住文件名
env/file/selectFile 读取所选行,填写加工列表并切回刀路页
env/file/setDir、filter 提交目录或筛选条件后,重新读取目录
env/file/selectAllFile 选取当前目录表中的全部文件

几组数据各管一件事:

参数 本例中的用途 不要混成什么
#802 当前目录及其文件记录 当前加工文件
#802.description 最近单击的文件名 所有选中行,或完整路径
#6.item[...] “选取”时临时收到的表格行号 长期保存的客户参数
#334 加工列表,一组对应一个加工文件及其设置 磁盘目录列表
#403 当前加工文件路径 页面上所有文件的集合
#9047 程序文字区要显示的文件路径 必然等于正在加工的文件
#810 程序页当前显示哪个子页 文件有效性或加工启动命令

本例可以顺着这条线读:目录 → 文件表 → 所选行号 → 完整路径 → 加工列表和文字显示。

3.进入文件页,怎样把目录变成表格

“文件管理”入口中的原有事件是:

-A:(clickedEvent:/env/file/filepage[0](#810=1))

它先把 #810 设为 1,再调用 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

按行理解:

  1. disk 取得盘符,把结果放进 #803,供左侧盘符表使用。
  2. #811.version 记录本次运行中是否已装入该页。为 1 就跳到末尾。
  3. 第一次进入,把标志设为 1,再让 dir 读取 #802 指定的目录。
  4. 把原有 file.ui 路径交给 #811.itemdesc[0]。
  5. 刷新主框架内的 fileFrame,在这个位置装入文件页。

其中这一行最值得看懂:

widgetFunc["dir",#802,"",802]

第二项 #802 取的是目录字符串,第四项 802 是接收结果的参数编号。同一组参数既记目录,又保存读到的各条记录。第四项不能随手改成 #802。

dir 给每一条记录填写以下内容:

字段 图 2 文件行所对应的内容
#802.item[i] 文件名 圆形铣底.nc
#802.itemtitle[i] 包含磁盘、目录和文件名的完整路径
#802.itemversion[i] 文件为 0,目录为 1
#802.itemmax[i] 文件大小;本例为 4662 字节
#802.itemunit[i] 后缀,本例为 nc
#802.itemdesc[i] 读取目录时取得的修改时间

这里 .itemmax 保存文件大小,.itemunit 保存后缀;不能套用参数输入页中“上限”和“单位”的解释。

文件表对象名为 filebrows。它的行数定义为 -rows:#802itemnum,每条目录记录生成一行。本例第 0 行是 ..,第 1 行才是 NC 文件;程序不能假定第 0 行一定是文件。

#802.title 与当前读取路径相等时,dir 不列出 ..。这是控制父目录行的显示,不是限制用户只能访问某个目录。

env/main 在初始化时清掉 #811.version 和原子页路径,因此下次运行可以重新装页。file-install 用于安装参数,不在这个每次进页的调用链中。

4.单击文件,为什么还没有完成选取

文件表第一列的单击事件原文是:

-A: (clickedEvent:/env/file/enterDir[0](#2=%%))

%% 在这里交给脚本的是当前表格行号。图 2 点的是第 1 行,所以先准备 #2=1,再运行下面的完整脚本:

IF#802.itemversion[#2]==0GOTO1
widgetFunc["dir",#802.itemtitle[#2],"",802]
#802.description=""
GOTO2
N1
#802.description=#802.item[#2]
N2

如果是目录,就读取该目录,清空底部文件名;如果是文件,就跳到 N1,把名称写进 #802.description。

底部“文件名”框绑定的是 -T(#802description),所以写入这个字段后,界面就显示名称。这几行没有填写 #334,也没有更改 #403 或 #9047。 图 2 的文件名只是最近单击记录。

这也说明:直接在“文件名”框输入一个名称,并不等于在表格中选中了那一行。“选取”读取的是表格的选中行,不能只凭这个输入框判断。

原有文件名单元格还配置了双击调用 selectFile。本篇用“单击文件 → 按选取”讲清两步;目录双击和触摸下的连续事件顺序,留待完整应用核对。

5.按“选取”后,完整脚本做了什么

右下角“选取”按钮的对象名为 pushButton_4,点击事件调用 /env/file/selectFile[0]。脚本原文如下,保留原来的编号和写法:

IF[#319.item[3]==1]+[#319.item[7]==1]GOTO2

widgetFunc["QTableWidget","filebrows","getSelectedIndex",6]
IF#6.itemnum==0GOTO1
#334.groupnum=#6.itemnum
#500=0
WHILE#500<#6.itemnumDO1
#334.item[20*#500]=1
#334.item[20*#500+1]=#802.itemtitle[#6.item[#500]]
#334.item[20*#500+2]=0
#500=#500+1
END1

#403=#334.item[1]
#9047=#334.item[1]
#324.item[2]="00:00:00.000"
#9048.channel=0
#9048.permission=widgetFunc["getFileLineNum","","",#403]
#331.item[2]=1
#810=0

#333.item[1]=0
#333.item[13]=1

#904=FIX[[#904.itemnum-1]/10]
#904.item[#904.itemnum-1]=#324
#904.itemdesc[#904.itemnum-1]=#1107.itemtitle[11]+#403
#904.itemversion[#904.itemnum-1]=0
#904.itemnum=#904.itemnum+1

GOTO1
N2
widgetFunc["messageBox",#1107.itemtitle[27],#1107.itemtitle[28],""]
N1

先把它分成五段看:

段落 作用 本例结果
首行状态检查 规定的解释器忙状态下转去提示,不继续换文件 本例为空闲,继续
getSelectedIndex 从当前窗体的 filebrows 取得所选行,放到临时参数 #6 #6.itemnum=1,#6.item[0]=1
WHILE 循环 每个所选行填写一组加工文件 第一组使用 NC 文件的完整路径
#403 到 #333 更新当前文件、显示文件、行位置、时间、计数和子页 返回刀路页,显示本例程序
最后的 #904 追加选择文件的日志 日志记录所选路径

其中 #333.item[1] 是已完成计数,#333.item[13] 是循环次数。选取后分别设为 0 和 1,所以图 4 显示 0/1;后者不是“请求生成预览”的开关。#9048.permission 在这里存放文件行数,也不能按字段名称把它理解为账号权限。

未选中任何行时,脚本在 IF#6.itemnum==0GOTO1 退出。本次已核对:此时加工列表和当前文件保持不变。

取选中行的函数在当前脚本所在窗体找 filebrows。以后做另一个窗口时,不能只复制这句,而不给那个窗口建立对应的表格。

6.加工列表为何每隔 20 个字段写一次

本版本的 #334 按加工组保存。每组展开为 20 个字段,因此第 g 组从 20*g 开始:

要填的内容 第 1 组,组号 0 第 2 组,组号 1
是否参与加工 #334.item[0] #334.item[20]
完整文件路径 #334.item[1] #334.item[21]
起始行 #334.item[2] #334.item[22]
结束行 #334.item[3] #334.item[23]
X 偏移 #334.item[4] #334.item[24]

本例只有一行被选中,循环中 #500=0。于是文件名这一句实际取的是 #802.itemtitle[#6.item[0]],也就是 #802.itemtitle[1],再写到 #334.item[1]。

注意这里有两个不同的 1:一个是文件表行号,一个是第一加工组的文件路径字段号。恰好相同,不表示它们总是相同。选中第 4 行时,第一组文件路径依然写到 #334.item[1]。

文件表允许多选;每个被选中的行都会进入循环。最终加工顺序应以加工列表为准,不要把它当成保证按照鼠标点击先后排序。

重选文件时,标准脚本只明确写了每组的 0、1、2 号字段。 如果原加工组仍被保留,结束行、偏移和旋转设置也可能被保留。图 4 中的默认值来自本例空加工组,不是脚本把所有这些字段重新清零。

右下角的“全部选取”使用 selectAllFile。它遍历当前目录记录,按文件标记选取,不依赖当前高亮行,也不递归读取子目录。本次目录中只有一个文件,因此它得到的也是这一组程序。

普通“选取”脚本没有单独排除目录行。使用时确认选中的是文件;以后定制选择入口时,也应明确是否需要增加目录检查。这里不修改原功能。

7.程序文字和刀路,分别怎样取得

刚才脚本连续写了:

#403=#334.item[1]
#9047=#334.item[1]

第一行设置当前加工文件,第二行设置程序文字区要读的文件。两处在这一步使用同一条路径。

主 UI 中程序文字区的绑定原文为:

-T(#9047<<#9048.channel) -D
-C(#319.item3==1||#319.item7==1) 
-R0

#9047 给出文件,#9048.channel 给出显示行位置;-D 让它参加界面更新,后面的条件控制忙状态下只读。软件在装载 UI 时,为这个位置建立实际的程序编辑控件。读者主要看绑定,不必按 .ui 里的控件类名去另写一套读文件代码。

软件会比较文件路径、修改时间和大小,发生变化时再读取文字。文件大小还必须小于 #9980.item[6]*1000 字节;打不开或超过这一显示条件时,文字区可能为空。getFileLineNum 也是读文件行数,不检查 G 代码是否合法。本例取得 324 行;失败或达到大小限制时可返回 -1。

#331.item[2]=1 请求清掉旧刀路。清旧刀路、显示新文字,都不是让 NC 解释器重新生成整份刀路的命令。 标准 selectFile 没有写入加工启动位。

图5:同一程序经单独离线解释后,在原生刀路预览中显示圆形刀路,右上角为仿真

点击截图可查看原图。

图 5 为对照同一程序的内容,本图在选取之后另行调用原有 NC 解释与绘图代码,离线生成左侧刀路;右侧文字和下方加工列表仍对应 圆形铣底.nc。这不是“按选取就立即生成刀路”的截图,也不是完整发布版点击仿真的验收结果。未启动机床调度;具体仿真与启动流程放到加工篇讲解。

还有一种常见操作:在已有加工列表里点另一行。它使用 env/funcscripts/selfilelist 更新 #9047 等显示数据,脚本没有同时给 #403 赋值。所以“我正在查看哪份程序”与“当前加工文件”需要分别判断。

8.路径和过滤器怎样交给脚本

原有两个输入框分别这样绑定:

-T(#802)
-D
-A: (Return:/env/file/setDir[1])
-T(#802unit)
-D
-A: (Return:/env/file/filter[1])

第一段是“文件路径”,第二段是“过滤器”。按回车时,输入先写回绑定字段,再执行 Return 对应脚本。setDir 的完整内容为:

#802.description=""
widgetFunc["dir",#802,"",802]

filter 的完整内容只有:

widgetFunc["dir",#802,"",802]

这两处正好说明:输入框负责把用户输入交给参数,短脚本负责让后续工作发生。 不需要每个输入框都重新实现文件枚举。

多个筛选式用空格分隔,如 *.nc *.tap。截图中的 *.nc *.txt *.tap *.cnc 就是四种筛选式。它只筛选文件名,目录仍然列出,也不会判断文件内容能否加工。

本次用原输入事件核对了两种结果:提交 *.nc 后,文件仍在表内,最近单击的文件名保留;重新提交当前目录后,文件表仍在,底部“文件名”被清空。这与两个脚本是否包含清空语句一致。

再次切到“文件管理”时,filepage 因 #811.version==1 跳过重新读目录。因此外部程序刚生成的文件没有出现时,可以重新提交目录或过滤器;单纯切走再回来,不保证刷新文件表。

9.书签、浏览和其他入口放在哪里

读懂主线后,再看页面周围的原有功能:

操作 相关脚本和数据 需要分清
选择盘符 selectDir,从 #803.itemtitle[...] 取得目录 换浏览目录,不直接换加工程序
“添加到书签” addSticky,把当前目录追加到 #804.itemtitle[...] 保存的是目录,不是某个 NC 文件
单击书签 stickyDir,读取该目录 路径仍需在当前电脑存在
双击书签 delSticky,删除相应书签项 移除记录,不删除磁盘目录
“浏览” browseFile,使用 #418 指定的外部程序 与按“选取”载入加工列表不同;多文件参数拼接另需核查
“复制、粘贴、删除” copy、paste、delete 属于磁盘文件操作,不是加工列表编辑

本篇没有执行外部浏览、复制、粘贴或删除,也未验证书签保存重启。相关脚本和限制可以查 文件操作详细资料。

底部 F1“加载文件”还是另一个入口,使用 env/funcscripts/selectfile 打开原生文件对话框。它还有与 #929.item[4] 有关的逆向处理及仿真启动分支,不能因为名称相似,就认为它和文件页的 selectFile 完全一样。分析组态时,要以实际按钮指向的路径为准。

10.以后定制文件相关功能,照这条线检查

如果客户以后提出“默认进入某个程序目录”“只显示某类文件”“让外部生成的程序进入列表”,先确定要接在哪一步:

想调整的内容 优先看哪里
浏览哪个目录 #802 和读取目录的入口
列出哪些类型 #802.unit,以及修改后是否重新执行 dir
表格显示哪些内容 file.ui 的 filebrows,与 #802 每行记录的对应关系
哪些行可以进入加工列表 选中行读取和 selectFile 循环;需要的目录、范围和文件存在检查
选好后显示哪份程序 #334、#403、#9047 及行位置的同步
是否重算刀路或开始加工 另看仿真、启动流程;不能从文本已显示推断

如果给文件表增加筛选行、另行排序或分页,要重新检查“可见行号 → #802 记录号”。当前脚本能直接使用行号,是因为原表一行对应一条目录记录。

常见问题可以这样查:

现象 先检查
底部已有文件名,按“选取”却没换程序 表格是否真的选中了行;文件名框不能代替选中集合
改目录后仍显示旧文件表 dir 是否读取成功;目录不存在时返回 -1,原记录不会先被清掉
文件已生成,切回来却看不到 是否只切了子页,没有重新读取目录
选好后仍有上一次的偏移或结束行 原加工组是否被复用;选择脚本未逐项清空这些设置
文件名对了,但程序文字为空 #9047 指向的文件、读权限和大小限制
文字有了,左侧没有新刀路 是否只完成选取,尚未运行相应的解释与绘图流程
改成多选后处理了错误文件 是否把最近单击名称当成多选集合,或改坏了行号对应关系

本篇先把现有选择流程读通,不增加客户专用目录、按钮或安装脚本。后续学习教导功能时,再看已有页面怎样把用户给出的动作和参数组织成 NC 程序。

上一课:坐标输入 · 下一课:启动、暂停、恢复和停止 · 阅读目录