右键菜单和多级菜单,是怎样做出来的

阅读目录 · English

上一篇通过移动“组件部署”按钮,认识了配置菜单。这一篇接着读菜单本身:一行名称从哪里来,右侧的小箭头怎样出现,为什么有的项目不能选、有的项目根本看不到,选择后又怎样把结果交给脚本。

我们仍使用标准软件已有功能。贯穿例子是从右侧控制区的菜单选择“内孔心/探测”,把它放到一个原有空位置,只核对配置结果,不点击探测按钮。

1.先从上一篇的一层菜单看起

图1:参数页原有功能键配置菜单,组件部署被勾选

点击截图可查看原图。

图 1 右键参数页原有 F5“组件部署”后出现的“功能键配置菜单”。这一菜单直接列出可选功能,没有再展开一层。

原入口中的关键一句是:

widgetFunc["PopMenu","","",915]

最后的 915 表示按参数 #915 的定义建立菜单。菜单的每一项主要来自参数子项,并不是另有一份 .ui 文件把这些菜单行逐个画出来。

上一课中,选择“空”或“组件部署”都会进入原 selmenufunc,由它改按钮配置。本课继续沿这个思路看有子菜单的情况;原有 F5 的配置没有在本课改动。

2.打开右侧控制区的多级菜单

图2:标准程序页,右上角显示超级管理员和仿真,右侧控制区第一排第五个位置为空

点击截图可查看原图。

图 2 从熟悉的“程序 → 刀路预览”开始。左侧显示原有程序的离线刀路,右侧是本课要看的控制区。第一排从左到右为“手轮引导、A+、Y+、Z+、空、空”,本例选择第五个位置。

在练习副本中,使用已有开发者账号登录,使右上角显示“超级管理员”。右键第一排第五个空位置,出现下面的菜单:

图3:原生手控操控功能键配置菜单,多个类别右侧有子菜单箭头

点击截图可查看原图。

图 3 菜单顶部的实际文字是“手控操控功能键配置菜单”。“空”前的勾表示这个位置当前为空。“手动控制”“对刀/探测”等行右侧的小箭头表示还有下一层。

展开 “对刀/探测”:

图4:原生对刀探测子菜单,内孔心探测可以选择,自动测量已被占用

点击截图可查看原图。

图 4 该子菜单直接从原生弹出菜单截取,图中显示“内孔心 探测”。它的名称在参数中带换行,菜单中作为一行显示;按钮上则分成两行。

选择 “内孔心 探测”,结果如下:

图5:原生控制区第五个位置出现内孔心探测,其他原有按钮保留

点击截图可查看原图。

图 5 第一排第五个位置显示“内孔心/探测”。这里只把已有功能放到按钮位置,未定义新的探测方式,也没有执行探测。

本课到看到图 5 的结果为止。 再次左键点击这个按钮,才会进入真正的探测功能。本课不执行该操作;探测输入窗口的读法已在 参数窗口篇 讲解。恢复原布局时,右键这个按钮,在第一层菜单选择“空”即可。

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

3.先找入口,再找菜单参数

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

文件或参数 本例看什么
env/maininterface/maininterface.ui 右侧现有按钮及对象名,本例为 ctrlButton5
env/mainInit 把 #911 中的动作与位置属性装到右侧按钮上
env/program/ctrlfuncmenu 检查开发者身份,打开第一层菜单
env/program/selctrlfuncmenu 选择后把功能放到刚才右键的位置
#910 第一层菜单;主值暂存当前功能编号
#924 “对刀/探测”子菜单
#911 36 个位置及已有功能定义;主值暂存正在配置的位置
env/i18n/translatPack-0、translatPack-1 两种语言的菜单及功能名称

第五个位置编号为 4,它的位置属性原文是:

-A: (rightClickedEvent:/env/program/ctrlfuncmenu[0](#911=4<<#910=#911item4))
-C(#911item4!=0||#1026item0==2)
-V

右键先记录 #911=4,再把这个位置当前选的功能交给 #910,随后运行 ctrlfuncmenu。后两行让有功能的位置可见;空位置则只有开发者身份能看见,以便配置。

ctrlfuncmenu 的完整内容是:

IF#1026.item[0]!=2GOTO1
widgetFunc["PopMenu","","",910]
N1

与上一篇的区别是菜单号从 915 换成了 910。配置权限来自入口脚本的判断,不是 PopMenu 自动要求每个菜单都必须以开发者身份打开。

4.一组菜单参数,各字段分别负责什么

以下是本系统 PopMenu 实际读取的主要字段。先对照本例,不必一次记住所有名称。

字段 菜单中怎样使用 本例
title 整个菜单的标题;成为子菜单时,父菜单中显示这个标题 #924.title 为“对刀/探测”
description 非空时作为该菜单的样式文字;为空时使用所在窗体的样式 决定原生菜单的颜色等外观
itemnum 菜单参数的子项数量 #924 有 12 个子项,编号 0~11
itemtitle[i] 普通菜单项的名称 第 6 项是“内孔心/探测”
item[i] 该项的界面属性文字,如勾选、禁用和显示条件 检查是否已选、是否已占用
itemmin[i] 区分普通项、分隔线或子菜单 #910.itemmin[9]=924 指向子菜单
itemunit[i] 普通项的图标文件名,以及可选的建立条件 可写成“图标文件名 << 条件”
itemdesc[i] 选中后的脚本路径及准备赋值 /env/program/selctrlfuncmenu<<#910=50
itemversion[i] 普通项选择后采用哪类脚本调用设置 本例为 1,调用 Qt 组态脚本

这些字段在这里按菜单规则使用。itemmin 不是数值输入的下限,itemunit 不是毫米等单位,itemdesc 也不是一段帮助说明。要按实际用途读。

菜单项可以用 item[i] 中的 -T(...) 改变显示文字;没有这种覆盖时使用 itemtitle[i]。本例功能名称来自 itemtitle,不用另外写一组 -T。

5.一行怎样变成子菜单

关键就是 itemmin:

值 软件怎样建立这一项
0 普通菜单项,点击后按该项的脚本定义处理
小于 0 分隔线
大于 0 把这个数作为另一组菜单参数号,再建立下一层

在本例第一层菜单中,可以核对这些实际值:

字段 当前值 结果
#910.itemmin[1] -1 标题行之后的分隔线,外观由样式决定
#910.itemmin[2] 0 普通的“空”菜单项
#910.itemmin[3] 919 “手动控制”子菜单
#910.itemmin[9] 924 “对刀/探测”子菜单
#910.itemmin[11] 926 “工艺策略”子菜单

#910.itemtitle[9] 当前为空,但图 3 仍显示“对刀/探测”,原因是:这一行是子菜单,显示的是 #924.title。 改父项的空名称,不一定会改到屏幕上看到的标题。

标题行也要分清。图 3 顶部不可选择的“手控操控功能键配置菜单”,是第 0 项的名称,配合如下属性显示:

-C(1)
-E0

条件恒成立,所以这行不可选。它不是设置了 #910.title 就自动额外生成的一行;原配置专门保留了第 0 项。

菜单还可以继续分层。现有配置中,#910 的第 11 项指向 #926,#926.itemmin[9] 又指向 #950,后者标题是“轴映射多面雕”。这项带 #929item7==1 的建立条件;本次装载值为 0,因此截图中没有展开这条路径。本课没有为取图开启该功能。当前英文语言包也未提供这组 #950 名称的英文赋值,不能把自行翻译的文字说成现有英文界面。

设计下一层时,应指向另一组正确的菜单参数,保持层次清楚。当前建立过程没有检测“子菜单又指回自己或上一级”的循环,不能这样相互引用。

6.把“内孔心/探测”这一项完整读下来

这一项在 #924 的子项 6,现有定义如下:

字段 当前内容
#924.itemtitle[6] 中文为“内孔心”换行“探测”;英文为 InnerHole 换行 Probe
#924.itemmin[6] 0,普通项
#924.itemunit[6] 空字符串,没有图标,也没有额外的建立条件
#924.itemdesc[6] /env/program/selctrlfuncmenu<<#910=50
#924.itemversion[6] 1

#924.item[6] 中的属性原文为:

-C(#910==50)
-R0
-C(#911item0==50||#911item1==50||#911item2==50||#911item3==50||#911item4==50||#911item5==50||#911item6==50||#911item7==50||#911item8==50||#911item9==50||#911item10==50||#911item11==50||#911item12==50||#911item13==50||#911item14==50||#911item15==50||#911item16==50||#911item17==50||#911item18==50||#911item19==50||#911item20==50||#911item21==50||#911item22==50||#911item23==50||#911item24==50||#911item25==50||#911item26==50||#911item27==50||#911item28==50||#911item29==50||#911item30==50||#911item31==50||#911item32==50||#911item33==50||#911item34==50||#911item35==50)
-E1

长条件只是逐一检查 36 个位置有没有使用功能 50。先读懂前两个位置,再顺着同样的写法往后看即可:

因此,选好后再次右键同一个按钮,该项既被勾选,又不能重复选择;右键另一个空位置时,它没有勾选,但仍因已被占用而不能选择。本次两种情况都已在原生菜单中核对。

本例一共出现三个不同编号:

编号 表示什么
4 第五个按钮的位置
6 “对刀/探测”菜单中的原始子项号
50 “内孔心/探测”的功能号

这三个数不需要相同。后面找动作要用功能号 50,找菜单名称要用子项号 6,找要更新的按钮则用位置号 4。

7.不显示、不可选和打勾,是三件事

图6:原生手动控制子菜单,已有位置使用的X/Y/Z/A手控项不可选,B/C项仍可选

点击截图可查看原图。

图 6 从另一个空位置展开“手动控制”。当前配置中 X/Y/Z/A 的相应手控功能已放在面板上,B/C 项未放置;菜单显示情况反映的是功能配置,不表示某个轴正在运动。

状态 本系统菜单怎样实现 看到什么
不建立这项 itemunit 中 << 后的条件不成立 菜单中没有这行
已建立但隐藏 普通项的属性中使用 -C(...) 配合 -V 或 -V编号 该动作不显示;不能据此认为参数被删除
不允许选择 属性中的 -E编号 指定条件成立 名称仍在,但不能选
当前已选中 属性中的 -R编号 指定条件成立 名称前出现勾选

-E1 的 1 是条件列表的编号,不是功能号,也不是第几行菜单。-R 在这里控制菜单勾选,不能按输入框的“只读”来解释。原有样式可能把不可选项画成亮底,不能只用颜色深浅作判断。

看一个原有建立条件:#919.itemunit[0] 的全文是:

<<#912itemmax0==1

<< 左侧为空,表示没有图标;右侧检查该轴的配置条件。成立时才建立“X+手控”。第 1 项“X-手控”使用同样条件。

本次局部核对中,临时把这个条件读取的值从 1 改为 0,重新打开菜单后,X+和X-两行不再建立;恢复为 1 后重新打开,两行又出现。其他轴的菜单项保留。这只是核对程序中的内存对照,不是要求读者为练习菜单修改机床轴配置。

另一个例子是第一层的刀库菜单:#910.itemunit[12] 为 <<#901item0!=0。本次刀库类型为 0,所以图 3 没有这一分支。

图 4 的子菜单虽然定义了 12 项,当前只显示 10 项;另外两项被各自条件过滤。可见行从上往下数的位置,不等于原始参数子项号。 隐藏项没有把后面的 #924.itemdesc[6] 变成别的编号。

PopMenu 每次打开时建立菜单并检查条件。修改菜单文字或建立条件后,应关闭再重新打开核对;不要把 -D 理解为当前悬停的弹出菜单会自动持续重建所有项目。

8.图标、名称和菜单外观放在哪里

当前本例没有设置菜单图标。源码支持的读取位置如下,学习时先知道去哪里找即可:

对象 设置位置 读取规则
普通菜单项图标 该项的 itemunit[i] 中 << 前的文字;没有 << 时使用整个字符串 软件在运行目录的 images/ 下寻找该文件
普通菜单项的建立条件 同一字段的 << 后一段 无 << 时不附加这一条件;左侧可以留空
子菜单入口图标 子菜单参数本身的 unit,例如子菜单 924 对应 #924.unit 同样从 images/ 读取
子菜单名称 子菜单参数的 title 例如图 3 的“对刀/探测”来自 #924.title
普通项名称 itemtitle[i],或该项 -T(...) 给出的文字 中英文包可以给同一字段赋不同名称
菜单样式 该菜单参数的 description 非空时采用该段样式;为空时用所在窗体的样式

有一个容易弄错的地方:父菜单中某项指向子菜单时,父项的 itemunit 仍可控制是否建立这一分支,但该入口的图标读取的是子菜单自己的 unit。不能照普通菜单项的办法只改父项图标文字。

图标和额外文字覆盖规则已按源码确认,本课没有新增图标或改名取图。引用文件应随组态资源一起交付,并核对实际文件是否存在。

9.选中菜单后,怎样把编号交给脚本

本项的选择定义原文是:

/env/program/selctrlfuncmenu<<#910=50

<< 前是要调用的选择脚本,后面是先执行的准备赋值。右键时已经记下 #911=4,现在选择菜单项又写入 #910=50。随后原脚本的完整两行是:

#911.item[#911]=#910
widgetFunc["setWidgetAttribute",#911.itemtitle[#911],"",#911.itemdesc[#911.item[#911]]+#911.itemunit[#911]]

把本例数值带进去,结果就是:

顺序 改变什么
1 #911.item[4] 写入 50,记住第五个位置选了该功能
2 找到 #911.itemtitle[4] 指定的 ctrlButton5,装入“50 号功能属性+第 4 号位置属性”

因此新按钮取得原功能的名称和动作,同时保留再次右键配置的入口。它没有更新 F1~F12 的 #9995,这点与上一篇参数页的四行脚本不同。

菜单项的 itemversion[6]=1 是本菜单调用 Qt 脚本的设置。不要把按钮事件路径里的 [1] 与它当作同一套编号:

菜单 itemversion 所请求的脚本类别
0 NC
1 主 Qt
2 辅助 Qt
3 工具 Qt

实际 Qt 调用还会结合当前窗体和脚本忙状态安排执行。本例保留原来的 1;不为了“让它更快”改成 NC。普通菜单项的动作入口来自 itemdesc,菜单建立过程会清掉 item 属性里解析出的事件列表,再采用这里的路径。

PopMenu 会等待菜单交互结束,但本分支选择脚本通过排队的调用执行。不能仅凭菜单已关闭,就假设写在 PopMenu 下一行的代码一定晚于选择脚本完成。 标准设计直接把更新放进 selctrlfuncmenu,所需编号也在调用前准备好;照这个流程理解即可。

10.配置探测按钮,与执行探测怎样分开

菜单回调到这里已经结束。真正的探测入口在已有的 #911.itemdesc[50] 中:

-T(#924itemtitle6)
-D
-C(#319item3==1)
-E0
-A: (clickedEvent:customprobe/centerprobing.nc[2])

这段表示按钮显示对应菜单名称,并配置点击时调用探测 NC。这里事件路径的 [2] 才表示 NC 通道,与上一节菜单 itemversion=1 各管不同操作。

所以应分别追两条路径:

用户操作 调用路径 本课是否执行
在子菜单中选“内孔心 探测” 菜单准备功能号 → selctrlfuncmenu → 设置按钮 已局部核对
左键点击配置好的探测按钮 按钮点击事件 → customprobe/centerprobing.nc 未执行

这使第 4 篇参数窗口、第 5 篇功能键和本篇菜单接起来:已有探测功能 → 菜单允许选择 → 把功能放到按钮 → 使用按钮时才进入该功能的参数与动作流程。

center-install 可以帮助追溯这些名称和动作当初如何定义,但它是以前组件部署留下的文件,后续不再调用。当前菜单使用已装载的参数和实际语言包;不能通过修改这个遗留文件来期待下次开菜单自动更新。

11.以后修改现有菜单,按什么顺序检查

先按下面的顺序读通现有定义,再决定改哪一项:

  1. 找入口。 从按钮事件找到脚本,确认 PopMenu 使用哪个参数号;如果没有弹菜单,先检查入口权限。
  2. 沿子菜单找目标。 读取父项的 itemmin,找到子菜单参数;不要只在父表里查可见名称。
  3. 确认原始子项号。 名称在哪一项,就对照同一项的条件和选择定义;不要按屏幕可见行重新编号。
  4. 分清改的是哪件事。 改名称看语言包及标题字段;改可选状态看条件;改选择结果看 itemdesc;改真正动作还要继续找功能定义。
  5. 完整检查关联。 本例涉及菜单 924 的第 6 项、功能 50、按钮位置 4;只改其中一个数字,其他地方不会自动变成新的正确对应关系。
  6. 重新打开核对。 看名称、层级、隐藏项、勾选和禁用,再检查选择后写入的参数、按钮文字和事件。保存及重启验证按实际交付流程单独进行。

常见现象可以这样查:

现象 先查哪里
没有右键菜单 按钮是否可见、启用,右键事件是否存在,入口身份检查是否通过
改了父项名称,子菜单标题没变 子菜单参数自己的 title
分隔线成了可点击的空行 itemmin 是否仍小于 0
参数有这项,但菜单看不到 itemunit 的建立条件,以及普通项的 -V 条件
菜单出现了,但该项不能选 -E 指向哪条条件,是否已有位置使用该功能
选择后改了别的按钮 右键时准备的位置参数是否正确,是否在选择前被其他脚本改写
写了点击事件,选菜单却没调用 普通菜单项应检查 itemdesc 和 itemversion;不能只照搬按钮的事件字段
图标不显示 普通项与子菜单图标字段是否用对,运行目录 images/ 中是否有对应文件
中文改好,英文仍是旧名称 对应语言包是否覆盖了同一个标题字段
菜单已关闭,后续数据还不是预期 后续处理是否安排在选择脚本里,是否误用了 PopMenu 后一行的时序

下一篇用主界面的轴配置继续读菜单:选中一个轴,怎样改变共用标记,又怎样让整行坐标显示或隐藏。

上一课:功能键配置 · 下一课:轴配置 · 阅读目录