ENVI 5.1二次开发之——新增事件处理介绍及综合应用

0
分享 2016-06-09
本文主要介绍ENVI 5.1新增的事件处理方法,并在最后提供一个为ENVI 5.1添加快捷键的补丁,利用的方法就是事件处理。
如果大家对于IDL中快速可视化的事件处理比较了解,那么学习ENVI 5.1的事件处理就很好上手了,基本上属于一套东西。需要声明的是,ENVI 5.1提供的事件是来自于ENVIView的,即当前选中View响应的事件,比如我们在ENVI当前视图点击鼠标、按下键盘等产生的事件。
在ENVI 5.1提供了三类事件处理类型和两种处理方法。事件处理类型分别为:
>>>鼠标事件:包括左键、中键、右键的单击和双击事件等;
>>>键盘事件:包括Ctrl、Shift、Esc、方向键、字母键等事件,以及组合按键;
>>>选择改变事件:包括图层选择变化时产生的事件等。
两种处理方法:
>>>函数:为每一类事件编写响应函数;
>>>类:编写事件响应类,可以处理各种事件类型。

1. 函数处理

1.1 鼠标事件

鼠标事件有四种类型,可以配合使用,比如ENVI按下中键可以进行平移就是利用鼠标按下和移动事件实现的。鼠标所有事件类型及其函数格式如下表所示。
表:鼠标事件类型与函数格式

表:鼠标事件函数的参数介绍


简单举例,我们可以编写鼠标双击ENVI视图时响应的事件。在使用ENVI::GetView获取当前视图oView后,可以使用Mouse_Down_Handler关键字设置鼠标按下事件响应函数,格式如下(其中MouseDown_Handler为事件函数名):
oView.SetProperty, MOUSE_DOWN_HANDLER='MouseDown_Handler'
编写响应函数,实现在鼠标双击时弹出对话框,代码如下。其中Return返回值为0,则屏蔽ENVI原有鼠标按下事件;如果Return返回1,则保留。
在IDL工作台新建文件,将如下代码拷贝到编辑器,保存为Example_ENVI51_Event.pro,运行即可。如果修改了事件函数,可以编译一次即可生效。

FUNCTION MouseDown_Handler, oView, $
x, y, iButton, KeyMods, nClicks
; 获取当前ENVI
e = ENVI(/CURRENT)
; 判断鼠标左键双击
IF iButton EQ 1 AND nClicks EQ 2 THEN BEGIN
;弹出对话框
e.ReportError, 'The left mouse button double-click.', /INFORMATION
;屏蔽ENVI原有双击事件
RETURN, 0
ENDIF
; 保留其他鼠标事件,如果将此处的1改为0,则不能使用鼠标中键按下平移视图等功能。
RETURN, 1
END

PRO Example_ENVI51_Event
; Start the application
e = ENVI()
oView = e.GetView()
oView.SetProperty, $
MOUSE_DOWN_HANDLER='MouseDown_Handler'
END

运行效果如下,当鼠标在视图中双击时,弹出如下对话框:

图:双击弹出对话框
注:鼠标移动、弹起、滚轮等事件类似,不再赘述。

1.2 键盘事件

键盘事件响应函数格式如下:
Result = FunctionName(View, IsASCII, Character, KeyValue, X, Y, Press, Release, KeyMods)
表:键盘事件函数的参数介绍


举例说明,当我们按下ASCII按键时,弹出对话框显示按键。可以使用KEYBOARD_HANDLER属性设置键盘事件函数名,如下:
oView.SetProperty, KEYBOARD_HANDLER='KEYBOARD_Handler'
编写函数事件如下:
FUNCTION Keyboard_Handler, View, $
IsASCII, Character, KeyValue, X, Y, Press, Release, KeyMods

e = ENVI(/CURRENT)
; 为ASCII键盘时,弹出对话框
IF IsASCII AND Character NE 0 AND Press THEN BEGIN
e.ReportError, 'The pressed key is ' + $
STRING(Character)
RETURN, 0
ENDIF
RETURN, 1
END

编译代码后,鼠标选中ENVI当前视图,然后可以按下键盘(ASCII码按键),效果如下:
图:键盘事件效果

1.3 选择变化事件

找不到太合适的名字翻译这个事件类型,英文为Selection Change Event Handlers。简单来说就是在视图中的栅格、矢量等图层的选择状态改变时产生的事件。格式如下:
Result = FunctionName(View, Graphic, Mode, WasSelected)
表:选择变化事件函数的参数说明

因为实在想不到这种事件类型用来做什么,所以就简化了下ENVI帮助中提供的例子。功能如下:运行此段代码,会在ENVI视图打开两个栅格图层,并自动把鹰眼图打开。当我们平移视图时,鹰眼图会记录移动痕迹,此时当我们选择另一个图层时,鹰眼图中的痕迹会自动清除。
FUNCTION ExampleAPIEventsSelectionChangeHandler, View, $
graphic, mode, wasSelected
; 如果选择为栅格图像,并且之前未选择
IF ISA(graphic) && ISA(graphic, 'ENVIRASTERLAYER') $
&& ~wasSelected THEN BEGIN
; 清除鹰眼图内的痕迹
View.ClearSnailTrail
ENDIF
RETURN, 1 ; 执行默认事件
END

PRO ExampleAPIEventsSelection
; 启动ENVI 5.1
e = ENVI()
; 打开一个栅格图像
file = FILEPATH('qb_boulder_msi', ROOT_DIR=e.ROOT_DIR, $
SUBDIRECTORY = ['data'])
raster = e.OpenRaster(file)
; 获取视图,创建两个图层
oView = e.GetView()
v1layer1 = oView.CreateLayer(raster)
v1layer2 = oView.CreateLayer(raster, /CIR)
; 显示鹰眼图及其痕迹保留
oView.SHOW_OVERVIEW = 1
oView.SHOW_SNAIL_TRAIL = 1
; 设定选择变化事件响应函数
oView.SetProperty, $
ELECTION_CHANGE_HANDLER='ExampleAPIEventsSelectionChangeHandler'
END

2. 类处理

类处理的方式就是把上述所有的函数写为类的方法即可,可以方便的进行所有类型事件的编写。使用ENVIView的EVENT_HANDLER属性设置响应类的实例即可。格式如下:
Result = ENVIView.MouseDown(View, X, Y, Button, KeyMods, Clicks)
Result = ENVIView.MouseMotion(View, X, Y, KeyMods)
Result = ENVIView.MouseUp(View, X, Y, Button)
Result = ENVIView.MouseWheel(View, X, Y, Delta, KeyMods)
Result = ENVIView.KeyHandler(View, IsASCII, Character, KeyValue, X, Y, Press, Release, KeyMods)
Result = ENVIView.SelectChange(View, Graphic, Mode, WasSelected)
可以看到上边的参数与函数处理的参数完全一致,这里不再赘述。我们把上边编写的一个简单例子改写为类处理方法,以鼠标双击事件为例,保留帮助示例代码的键盘事件,即小写z实现放大,大写Z实现缩小。代码如下:
FUNCTION ExampleAPIEventsClass::MouseDown, View, $
X, Y, iButton, KeyMods, nClicks
; 获取当前ENVI
e = ENVI(/CURRENT)

; 判断鼠标左键双击
IF iButton EQ 1 AND nClicks EQ 2 THEN BEGIN
;弹出对话框
e.ReportError, 'The left mouse button double-click.', /INFORMATION
;屏蔽ENVI原有双击事件
RETURN, 0
ENDIF

END

FUNCTION ExampleAPIEventsClass::KeyHandler, View, $
IsASCII, Character, KeyValue, X, Y, Press, Release, KeyMods
; z 放大;Z 缩小
IF IsASCII && Press THEN BEGIN
CASE STRING(Character) OF
'z': view.ZOOM
'Z': view.ZOOM, /OUT
ELSE:
ENDCASE
ENDIF
RETURN, 0
END


PRO ExampleAPIEventsClass__define
; 事件类必须继承GraphicsEventAdapter.
void = {ExampleAPIEventsClass, INHERITS GraphicsEventAdapter, $
X0: 0, Y0:0, BUTTONDOWN:0, POLY:OBJ_NEW()}
END

PRO ExampleAPIEventsClass
; Launch the application
e = ENVI()
oView = e.GetView()
eventHandler = OBJ_NEW('ExampleAPIEventsClass')
oView.SetProperty, EVENT_HANDLER=eventHandler
END

3. 综合应用

使用事件处理有一些注意事项:
² 因为事件是对应视图的,所以当我们使用ENVI的菜单新建视图后,新视图是没有自定义事件的,需要运行一次扩展补丁(在Toolbox/Extensions/XXXXXX)即可。
² 如果系统只有一个中文输入法(如QQ输入法,非广告),需要在系统设置里添加一个英文输入法,然后在ENVI界面要启动非中文输入法(不是将QQ输入法状态修改为英文,这样是无效的),如下图所示。

图:添加输入法

下面提供一个ENVI功能扩展补丁,压缩包里边有pro和sav文件,功能描述如下表所示。
表:Add Shortcuts补丁具有的功能描述


sav文件可以放在如下路径,然后重启ENVI即可。
C:\Program Files\Exelis\ENVI51\extensions
使用方法两种:
>>>启动ENVI,双击运行Toolbox/Extensions/Add Shortcuts工具;
>>>直接双击打开add_shortcuts.sav文件运行即可;
>>>注:每次使用ENVI自带新建视图功能后,想在新视图使用自定义事件,需要再次运行Toolbox/Extensions/Add Shortcuts工具。

下载地址:http://vdisk.weibo.com/s/zrSeGYf9ha1pp

文章来源:http://blog.sina.com.cn/s/blog_764b1e9d0101cglr.html

0 个评论

要回复文章请先登录注册