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

本文主要介绍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按下中键可以进行平移就是利用鼠标按下和移动事件实现的。鼠标所有事件类型及其函数格式如下表所示。

表:鼠标事件类型与函数格式

事件类型

函数格式

鼠标按下

Result = FunctionName(ViewXYButtonKeyModsClicks)

鼠标移动

Result = FunctionName(ViewXYKeyMods)

鼠标弹起

Result = FunctionName(ViewXYButton)

鼠标滚轮

Result = FunctionName(ViewXYDeltaKeyMods)

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

参数名

含义

View

为ENVIView类的一个实例,表示响应鼠标事件的视图(View)。

X

鼠标X轴坐标位置,为设备坐标,视图左下角为[0, 0]。

Y

鼠标Y轴坐标位置,为设备坐标,视图左下角为[0, 0]。

Button

表示产生事件的鼠标按键:1为左键;2为中键;4为右键。

Delta

表示中键(滚轮)滚动的方向和次数。前滚为正数,后滚为负数。绝对值大小取决于鼠标设置,一般为较小整型,如+1、-1、+2、-2等。

KeyMods

组合键时使用。1为Shift;2为Control;4为Caps Lock;8为Alt。

Clicks

鼠标按下次数。1为单击;2为双击。

 

简单举例,我们可以编写鼠标双击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原有双击事件

   RETURN0

  ENDIF

  ; 保留其他鼠标事件,如果将此处的1改为0,则不能使用鼠标中键按下平移视图等功能。

  RETURN1

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(ViewIsASCIICharacterKeyValueXYPressReleaseKeyMods)

表:键盘事件函数的参数介绍

参数

含义

View

为ENVIView类的一个实例,表示响应鼠标事件的视图(View)。

IsASCII

非0值时:字节型,表示按键为ASCII按键(字母、数字、Tab、Enter等),Character参数返回字节型数值,使用string函数可以将其转换为ASCII码。

Character返回为69,则为E;返回13,则为Enter;

为0值时:KeyValue参数返回数值,表示产生事件的键。

Character

如果IsASCII为非0值,则Character为按键对应字节型数值。

否则返回0。

KeyValue

如果IsASCII为0,KeyValue表示按键,否则为0。可能的值如下:

   1: Shift

   2: Control

   3: Caps Lock

   4: Alt

   5: Left

   6: Right

   7: Up

   8: Down

   9: Page Up

   10: Page Down

   11: Home

   12: End

X

鼠标X轴坐标位置,为设备坐标,视图左下角为[0, 0]。

Y

鼠标Y轴坐标位置,为设备坐标,视图左下角为[0, 0]。

Press

返回为非0值,表示按下。

Release

返回为非0值,表示弹起。

KeyMods

组合按键时使用,可能的值如下:

1: Shift

2: Control

4: Caps Lock

8: Alt

 

举例说明,当我们按下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)

RETURN0

ENDIF

RETURN1

END

 

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

图:键盘事件效果

1.3   选择变化事件

找不到太合适的名字翻译这个事件类型,英文为Selection Change Event Handlers。简单来说就是在视图中的栅格、矢量等图层的选择状态改变时产生的事件。格式如下:

Result = FunctionName(ViewGraphicModeWasSelected)

表:选择变化事件函数的参数说明

参数名

含义

View

为ENVIView类的一个实例,表示响应鼠标事件的视图(View)。

Graphic

选中的图形对象,可能为ENVIRasterLayer或ENVIVectorLayer等。

Mode

返回值表示当前选择类型,可能的值如下:

   0: Unselect,取消选择

   1: Select,选择

   2: Toggled selection,切换选择

   3: Additive,增加选择

WasSelected

之前的选择状态。0为未选择;1为选择状态。

因为实在想不到这种事件类型用来做什么,所以就简化了下ENVI帮助中提供的例子。功能如下:运行此段代码,会在ENVI视图打开两个栅格图层,并自动把鹰眼图打开。当我们平移视图时,鹰眼图会记录移动痕迹,此时当我们选择另一个图层时,鹰眼图中的痕迹会自动清除。

FUNCTION ExampleAPIEventsSelectionChangeHandler, View, $

  graphic, mode, wasSelected

  ; 如果选择为栅格图像,并且之前未选择

  IF ISA(graphic) && ISA(graphic, 'ENVIRASTERLAYER') $

   && ~wasSelected THEN BEGIN

   ; 清除鹰眼图内的痕迹

   View.ClearSnailTrail

  ENDIF

  RETURN1 ; 执行默认事件

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原有双击事件

   RETURN0

  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

  RETURN0

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补丁具有的功能描述

快捷键

功能

方向键

可以上、下、左、右移动视图。

Ctrl+N

新建视图,使用此快捷键新建的视图自动含有自定义事件。

Ctrl+P

新建透视窗口,需要至少打开两个图层。

Esc

如果有两个或更多个视图窗口,可以关闭当前视图。

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

posted @ 2022-09-05 13:43  ENVI-IDL技术殿堂  阅读(285)  评论(0编辑  收藏  举报