加载中…
个人资料
MATLAB技术论坛
MATLAB技术论坛
  • 博客等级:
  • 博客积分:0
  • 博客访问:590,055
  • 关注人气:489
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[原创]在Simulink环境中添加配置自定义菜单

(2013-05-24 22:11:05)
分类: MATLAB
[原创]在Simulink环境中添加配置自定义菜单


写这个帖子主要是因为之前恒润科技给单位开发一个工具软件,需要和Simulink深度结合。但是在提需求的时候,他们坚定的说不能自定义Simulink配置环境(换句话说就是不能和Simulink整合,只能提供单独的工具),且已经咨询Mathworks,说没法在Simulink中添加自定义菜单等。

先预览下效果图,给大家一个感性的认识:

http://attach.matlabsky.com/data/attachment/forum/201305/24/214156mz1kkg16z0wjkz5z.png.thumb.jpg 

另外这里提供本文用到的sl_customization函数: http://www.matlabsky.com/static/image/filetype/unknown.gif sl_customization.m (3.04 KB, 下载次数: 0) 

其实本文中涉及的技术,可以在Simulink的公开文档轻易找到,只是大家没有注意而已!另外本文中讨论的技术,不仅仅可以修改Simulink的菜单,还可以修改Simulink中很多环境配置,比如对话框控制、库浏览器、Simulink首选项等很多方面。本文仅以自定义Simulink菜单做抛砖引玉的作用!

在Simulink编辑器和Stateflow编辑中,可以在以下列表中添加菜单或命令:

  • 顶级菜单的尾部
  • 右键菜单的首部或尾部
  • 工具条

1、注册用户界面自定义(Registering User Interface Customizations)
首先在MATLAB的搜索路径下,添加一个sl_customization()函数,简单说,此函数就是告诉Simulink您希望对Simulink环境做哪些修改。function sl_customization()函数接受一个输入参数cm,cm是一个自定义管理对象( customization manager object)。cm对象中内置了一些进行环境自定义的方法。启动Simulink的时候,程序会自动加载sl_customization文件。
  1. function sl_customization(cm)
  2. % 用于自定义Simulink环境配置
复制代码
2、添加自定义菜单函数(addCustomMenuFcn)
定制菜单主要用到cm对象的addCustomMenuFcn和addCustomFilterFcn两个方法。

(1)addCustomMenuFcn(stdMenuTag, menuSpecsFcn)方法。此方法的主要功能是,将menuSpecsFcn中自定义的条目添加到stdMenuTag菜单项目下,主要参数意义如下:

  1. cm = sl_customization_manager;
  2. cm.showWidgetIdAsToolTip=true;
复制代码
此时Simulink界面将变成如下样子,在原有菜单旁边会自动显示Simulink已有菜单的stdMenuTag
http://attach.matlabsky.com/data/attachment/forum/201305/24/192649xgohzzlo555zmquq.png.thumb.jpg 
当您不需要显示那个stdMenuTag时,在命令窗口执行
  1. cm.showWidgetIdAsToolTip=false;
复制代码
(1)addCustomFilterFcn(stdMenuItemID, filterFcn)方法。该方法主要是用于,禁用或激活stdMenuItemID菜单。本文不大算详细介绍,感兴趣的朋友可以看看帮助文档。

因此文件中的代码重新修改如下:
  1. function sl_customization(cm)
  2. % 用于自定义Simulink环境配置

  3. % 告诉Simulink根据MenuWeWantAdd()返回参数中指定的函数
  4. % 在'Simulink:EditMenu'菜单下添加新建菜单
  5. cm.addCustomMenuFcn('Simulink:EditMenu',@MenuWeWantAdd)
复制代码
3、定义新增菜单创建函数(Define Menu Create Function)
在第二步中,告诉Simulink根据MenuWeWantAdd()返回参数中指定的函数来创建新菜单项,但是到底是使用哪些函数以及添加哪些菜单我们还米有定义。因此在sl_customization.m文件中继续添加如下代码:
  1. function schemaFcns=MenuWeWantAdd(callbackInfo)
  2. % 返回用于创建新增菜单的函数,必须接受一个callbackInfo输入参数

  3. % 告诉Simulink分别使用下面的函数,来创建每个新增菜单项
  4. schemaFcns={...
  5.     @CreateNewMenu1 % 新增第1个菜单的函数
  6.     @CreateNewMenu2 % 新增第2个菜单的函数
  7.     @CreateNewMenu3};  % 新增第3个菜单的函数
复制代码
其中MenuWeWantAdd()函数就是告诉Simulink通过哪些函数来创建菜单。

其中的输入参数callbackInfo,是一个Callback Info对象,包含以下几个属性
属性 说明
uiObject 句柄,被点击菜单的父对象,Simulink编辑器或Stateflow编辑器
model 句柄,当前编辑器中显示的Simulink模型
userdata

4、定义新增Action菜单项(Define Action Menu Items)
虽然现在已经知道使用CreateNewMenu1()等函数来创建自定义菜单,但到底是什么菜单呢?,因此需要继续在sl_customization.m文件中添加如下代码:
  1. function schema=CreateNewMenu1(callbackInfo)
  2. % 用来创建NewMenu1菜单,必须接受一个callbackInfo输入参数

  3. % 创建一个schema对象的实例,用于定义新增菜单的内容
  4. schema=sl_action_schema; % Action Schema Object
  5.   
  6. % 指定菜单的显示名称,必须
  7. schema.label = '新增Action菜单';
  8. % 指定菜单响应函数,必须,可以是字符串,函数句柄或者cell数组
  9. schema.callback = @NewMenu1Callback;
  10. % 设置用户数据,非必须
  11. schema.userdata = '';

  12. function NewMenu1Callback(callbackInfo)
  13. % 点击NewMenu1菜单时的响应函数,必须接受一个callbackInfo输入参数
  14. msgbox('新增Action菜单,被临幸了!')
复制代码
Action Schema对象有以下属性
属性 取值 说明
tag 字符串,可选 菜单的唯一标识符,类似于Simulink:EditMenu的作用
label 字符串,必须 菜单的显示名称
state 字符串,可选,只能以下三个取值 'Enabled'(默认)、'Disabled'、'Hidden'
statustip 字符串,可选 当鼠标移动到菜单上时,状态栏显示的提示文本
userdata 任意数据,可选 用户之定义数据
accelerator 字符串,可选,例如,'CTR+K' 菜单快捷键
callback 字符串或函数句柄,必须 点击菜单时的回调函数
autoDisableWhen 字符串,可选,只能以下三个取值'Locked'(默认)、'Busy'、'Never' 什么时候自动禁用菜单

5、添加Toggole菜单按钮(Toggle Schema Object)
其实在第4步中定义的是Action Schema Object,也是点击菜单,当点击菜单时响应相应的回调,但是菜单的形状不发生变化。而Toggle Schema Object在点击以后会发生形状变化,比如点击以后外形会凹陷下去,或者在菜单前面有一个√

Toggle Schema Object和Action Schema Object的属性基本一致,只是Toggle对象多了一个checked属性,当摁下时,checked=='on',否则checked=='off'(默认)。另外Toggle对象是使用sl_toggle_schema创建实例的
  1. function schema=CreateNewMenu2(callbackInfo)
  2. % 用来创建NewMenu2菜单,必须接受一个callbackInfo输入参数

  3. % 创建一个schema对象的实例,用于定义新增菜单的内容
  4. schema=sl_toggle_schema; % 注意这里是一个Toggle
  5.   
  6. % 指定菜单的显示名称,必须
  7. schema.label = '新增Toggle菜单';
  8. % 指定菜单响应函数,必须
  9. schema.callback = @NewMenu2Callback;
  10. % 设置用户数据,非必须
  11. schema.userdata = '';

  12. function NewMenu2Callback(callbackInfo)
  13. % 点击NewMenu2菜单时的响应函数,必须接受一个callbackInfo输入参数
  14. msgbox('新增Toggle菜单,被临幸了!')
复制代码
6、定义多级子菜单(Container Schema Object)
第5和6步都是添加一个菜单项,下面尝试添加一个包含子菜单的项目试试。这个子菜单叫做Container Schema Object,使用sl_container_schema进行实例创建。Container Schema Object和前面两个对象属性基本相似,包含两个特殊属性:

(1)childrenFcns
Cell数组,指定创建子菜单函数的列表,等同于第2步中MenuWeWantAdd()的返回值。可以使用'separator'指定菜单之间的分割线。
  1. % 创建一个schema对象的实例,用于定义新增菜单的内容
  2. schema=sl_container_schema; % 注意这里是一个container

  3. % 子菜单创建函数,使用'separator'添加分割线
  4. schema.childrenFcns={
  5.     @CreateSubMenu1 % 子菜单创建函数1
  6.     'separator' % 菜单之间的分隔符,快乐的分割线
  7.     @CreateSubMenu2}; % 子菜单创建函数2
复制代码
(2)generateFcn
函数句柄,相当于第2步中的@MenuWeWantAdd,该函数返回一个cell数组。
  1. % 创建一个schema对象的实例,用于定义新增菜单的内容
  2. schema=sl_container_schema; % 注意这里是一个container

  3. % 子菜单生成函数,注意当设置了generateFcn时,自动屏蔽childrenFcns
  4. schema.generateFcn=@SubMenuWeWantAdd; % 返回生成子菜单的函数列表
复制代码
请注意,generateFcn的优先权高于childrenFcns,当定义了generateFcn属性,那么childrenFcns属性自动被屏蔽。根据上面的说明,继续在sl_customization.m文件中添加如下代码:
  1. function schema=CreateNewMenu3(callbackInfo)
  2. % 用来创建NewMenu3菜单,必须接受一个callbackInfo输入参数

  3. % 创建一个schema对象的实例,用于定义新增菜单的内容
  4. schema=sl_container_schema; % 注意这里是一个container
  5.   
  6. % 指定菜单的显示名称,必须
  7. schema.label = '新增Container菜单';

  8. % 注意包含子菜单的项目是没有Callback属性的
  9. % schema.callback = @NewMenu3Callback; % 该句无效

  10. % 子菜单创建函数
  11. schema.childrenFcns={
  12.     @CreateSubMenu1 % 子菜单创建函数1
  13.     'separator' % 菜单之间的分隔符,快乐的分割线
  14.     @CreateSubMenu2}; % 子菜单创建函数2

  15. % 子菜单生成函数,注意当设置了generateFcn时,自动屏蔽childrenFcns
  16. schema.generateFcn=@SubMenuWeWantAdd; % 返回生成子菜单的函数列表

  17. % 设置用户数据,非必须
  18. schema.userdata = '';

  19. function schemaFcns=SubMenuWeWantAdd(callbackInfo)
  20. schemaFcns={
  21.     @CreateSubMenu3 % 新增子菜单函数
  22.     };

  23. function schema=CreateSubMenu1(callbackInfo)
  24. schema=sl_action_schema;
  25. schema.label='新增子菜单1';
  26. schema.callback='msgbox(''新增子菜单1,被临幸了!'')';

  27. function schema=CreateSubMenu2(callbackInfo)
  28. schema=sl_action_schema;
  29. schema.label='新增子菜单2';
  30. schema.callback='msgbox(''新增子菜单2,被临幸了!'')';

  31. function schema=CreateSubMenu3(callbackInfo)
  32. schema=sl_action_schema;
  33. schema.label='新增子菜单3';
  34. schema.callback='msgbox(''新增子菜单3,被临幸了!'')';
复制代码
7、让自定义立即菜单生效
好不容易编写好了上面的sl_customization.m,想立即看看效果,不过很惋惜的告诉您,您必须重启MATLAB,否不会生效。不过也可以在Command Windows中执行以下命令:
  1. sl_refresh_customizations
复制代码
至于效果可以查看本文最头部的图片!

请注意,在Window系统中,在sl_customization中设置断点,那么Simulink将不会执行设置断点的函数,因此如果想调试sl_customization文件,请使用命令行的形式,比如dbstop,千万不要在编辑器中直接设置断点。

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有