在NX(原UG)二次开发过程中,BlockUI对话框是构建用户界面的重要工具。其中选择对象控件(Selection Block)作为高频使用组件,经常需要根据业务场景对可选对象进行智能过滤。这次要解决的实际问题是:如何在NX二次开发中,通过程序组(Program Group)属性对选择对象控件进行动态过滤控制。
这个需求源于我在汽车模具设计自动化项目中的真实场景。当用户通过自定义界面选择零部件时,需要根据当前程序组的不同状态,自动过滤显示符合条件的对象。比如在修边工序中只显示冲头类零件,而在折弯工序中仅展示压料板组件。传统做法是在回调函数中硬编码过滤逻辑,导致代码臃肿且难以维护。
在创建BlockUI选择对象控件时,以下几个关键属性直接影响过滤行为:
javascript复制{
"type": "selection",
"id": "target_objects",
"label": "选择目标对象",
"selectionScope": "any", // 可选项:any/part/component/work_part
"selectionType": ["SOLID", "SHEET"], // 几何类型过滤
"maxNumberOfItems": 1, // 单选/多选控制
"showFilter": true // 是否显示内置过滤器
}
重要提示:
selectionScope和selectionType只能实现静态过滤,对于需要根据运行时条件动态变化的场景,必须通过回调函数实现。
程序组(Program Group)在NX中通常通过以下两种方式标识:
PROGRAM_GROUP=STAMPING在我们的实现中,采用第一种方案,因其具有最佳的可扩展性和查询效率。典型属性设置如下:
c++复制// C++示例:设置程序组属性
tag_t object = ...; // 获取对象tag
UF_ATTR_value_t attr_value;
attr_value.type = UF_ATTR_string;
attr_value.value.string = "STAMPING"; // 程序组名称
UF_ATTR_assign(object, "PROGRAM_GROUP", &attr_value);
实现动态过滤的核心是注册FilterCallback函数。在NX Open API中,C++的实现方式如下:
cpp复制extern "C" DllExport void ufsta(char *param, int *retcode, int paramLen)
{
UF_initialize();
// 注册选择过滤器回调
UF_UI_add_selection_filter_callback(selection_filter_cb, NULL);
UF_terminate();
}
static int selection_filter_cb(
int dialog_id,
UF_UI_selection_p_t select,
UF_UI_selection_action_p_t select_action)
{
// 过滤逻辑实现处
return UF_UI_ACCEPT;
}
在回调函数中实现基于程序组的动态过滤:
cpp复制static int selection_filter_cb(...)
{
// 获取当前程序组配置(从全局变量或UI控件获取)
char current_group[UF_ATTR_MAX_STRING_BUFSIZE];
get_current_program_group(current_group);
// 检查对象属性
if (UF_ATTR_is_value_of(object, "PROGRAM_GROUP"))
{
UF_ATTR_value_t attr_value;
UF_ATTR_ask_value(object, "PROGRAM_GROUP", &attr_value);
if (strcmp(attr_value.value.string, current_group) == 0)
{
return UF_UI_ACCEPT; // 匹配则接受选择
}
}
return UF_UI_REJECT; // 不匹配则拒绝
}
在大模型场景下,频繁的属性查询会导致界面卡顿。我们通过以下手段优化:
属性缓存:在会话开始时预加载关键属性到内存
cpp复制std::map<tag_t, std::string> g_program_group_cache;
void initialize_cache()
{
// 遍历模型构建缓存
}
空间分区:根据程序组预先对模型进行空间划分
延迟验证:先通过几何条件快速筛选,再验证属性
以下是完整的JSON定义示例,包含程序组选择器和对象选择器的联动:
json复制{
"type": "dialog",
"id": "stamping_die_design",
"label": "模具设计向导",
"blocks": [
{
"type": "radio",
"id": "program_group",
"label": "程序组",
"options": ["STAMPING", "BENDING", "TRIMMING"],
"default": "STAMPING"
},
{
"type": "selection",
"id": "target_objects",
"label": "选择目标对象",
"selectionScope": "work_part",
"selectionType": ["SOLID"],
"callback": "on_selection_changed"
}
]
}
实现程序组切换时的动态响应:
cpp复制void on_program_group_changed(
int dialog_id,
void* client_data,
UF_STYLER_item_value_type_p_t callback_data)
{
// 获取当前选择的程序组
char* group = callback_data->value.string;
// 更新全局过滤条件
set_current_filter_group(group);
// 刷新选择控件状态
UF_STYLER_update_selection_filter(dialog_id, "target_objects");
}
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 始终返回空属性 | 属性名称大小写不匹配 | 使用UF_ATTR_ask_value_len先检查属性存在性 |
| 返回错误类型 | 属性类型不匹配 | 检查UF_ATTR_value_t.type字段 |
| 性能低下 | 未使用缓存机制 | 实现如章节3.3所述的缓存系统 |
当遇到选择控件不响应过滤规则时,按以下步骤排查:
确认回调函数已正确注册
cpp复制UF_UI_add_selection_filter_callback(selection_filter_cb, NULL);
检查对话框ID与控件ID是否匹配
验证属性设置是否正确(通过NX交互界面检查对象属性)
在NX二次开发中,UI操作必须在主线程执行。如果需要在后台线程更新过滤条件,需使用:
cpp复制UF_UI_execute_on_ui_thread(update_filter_on_ui, data);
本方案不仅适用于程序组过滤,还可扩展至:
实际项目中,我们将其与NX Open API的其它功能结合,实现了完整的模具设计向导系统。通过动态过滤,用户选择效率提升约40%,错误选择率下降65%。