LearningENVI&IDL分享 http://blog.sciencenet.cn/u/dongyanqing Learning ENVI&IDL

博文

IDL界面和对象参数或数据传递之万能的uValue

已有 11382 次阅读 2012-12-12 19:10 |个人分类:IDL技术|系统分类:科研笔记| 界面, 对象, IDL, 参数传递, uvalue

     IDL中的数据传递有很多方法,函数或过程可以直接进行参数变量的传入和传出,界面或对象也可以进行数据的存储和传递。如对界面组件的参数传递,有下面方法:

界面程序下的数据传递包括下面三种:(1)系统变量;(2Common;(3)组件的uValue。经常用的是第三种方法,界面程序利用最顶级组件的uValue传递各种类型数据,一般用结构体或指针进行。

附界面传递的示例代码,注意代码中的注释和鼠标在界面中移动时鼠标信息如何在对话框中显示的。

;+

;      IDL语言程序设计》

; --数据快速可视化与ENVI二次开发(配盘)

;

; 示例源代码

;

; 作者: 董彦卿

;

; 联系方式:sdlcdyq@sina.com

;

;-

;界面关闭响应程序

PRO WIDGET_EXAMPLES_CLEANUP, tlb

  ;获取uValue

  WIDGET_CONTROL,tlb,get_uvalue=pstate

  ;因是指针,故需要销毁

  PTR_FREE, pState

END

;界面事件响应程序

PRO  WIDGET_EXAMPLES_EVENT, event

 

  ;获得顶baseuvalue,即组件信息指针结构体

  WIDGET_CONTROL,event.TOP,get_uvalue=pstate

 

  CASE TAG_NAMES(event,/STRUCTURE_NAME) OF

    ;关闭事件

    'WIDGET_KILL_REQUEST': BEGIN

      ;提示是否关闭

      tmp = DIALOG_MESSAGE('确认关闭?',$

        title ='关闭系统',/question)

      IF tmp EQ 'Yes' THEN BEGIN

        ;注意销毁之前创建的指针

        PTR_FREE, pState

        ;销毁界面

        WIDGET_CONTROL,event.TOP,/destroy

        RETURN

      ENDIF

      RETURN

    END

    ;draw区域

    'WIDGET_DRAW': BEGIN

   

      CASE event.TYPE OF

        ;注意不同的类型对应的不同的事件

        ;键盘和鼠标等各自事件的结构体内容

        0: BEGIN

          CASE event.PRESS OF

            1: value = '左键按下'

            2: value = '中键按下'

            4: BEGIN

              value = '右键按下'

              ;弹出右键菜单

              WIDGET_DISPLAYCONTEXTMENU, event.ID, event.X, $

                event.Y, (*pState).CONTEXTBASE 

            END

            ELSE: PRINT,event.PRESS

          ENDCASE

        END

        1: BEGIN

          CASE event.RELEASE OF

            1: value = '左键释放'

            2: value = '中键释放'

            4: value = '右键释放'

            ELSE: PRINT,event.RELEASE

          ENDCASE

        END

        2: value = '鼠标移动'

        7: BEGIN

          IF event.CLICKS GT 0 THEN value='滚轮前滚' $

          ELSE value='滚轮后滚'

        END

        4:  BEGIN

          value = '暴露事件'

          ;设置显示组件的大小

          drawSize  = WIDGET_INFO((*pState).MYDRAW,/Geom)

          ;适应性显示

          TVSCL,CONGRID(DIST(400),drawSize.XSIZE,drawSize.YSIZE)

        END

        5: value = 'key = ' +STRTRIM(STRING(event.CH),2)

        6: value = 'key = ' +STRTRIM(STRING(event.CH),2)

        ELSE:PRINT,event.TYPE

      ENDCASE

      ;

      WIDGET_CONTROL,(*pstate).TEXT1,set_value= value

    END

    ELSE:

  ENDCASE

 

  ;获取当前组件的uName

  uName = WIDGET_INFO(event.ID,/uname)

  ;点击了界面上按钮

  IF uName EQ 'button' THEN BEGIN

    tmp = DIALOG_MESSAGE((*pState).TESTSTR,/Infor)

  ENDIF

  ;点击了右键菜单中的按钮

  IF uName EQ 'contexButton1' THEN tmp = DIALOG_MESSAGE('右键菜单1',/infor)

  IF uName EQ 'contexButton2' THEN tmp = DIALOG_MESSAGE('右键菜单2',/infor)

  ;修改界面大小

  IF uName EQ 'tlb' THEN BEGIN

    ;显示组件大小适应程序大小

    drawXSize = event.X -(*pState).DRAWSPACE[0]

    drawYSize = event.Y -(*pState).DRAWSPACE[1]

    ;设置tlb大小(可忽略,因Draw组件后面已经设置了大小)

    WIDGET_CONTROL,event.TOP,xSize = event.X,ySize = event.Y

    ;设置显示组件的大小

    WIDGET_CONTROL,(*pState).MYDRAW,xsize = drawXSize, ySize = drawYSize

    ;适应性显示

    TVSCL,CONGRID(DIST(400),drawXSize,drawYSize)

  ENDIF

END

;

PRO WIDGET_EXAMPLES

 

  ; 创建一个主Base窗体

  base1 = WIDGET_BASE(TITLE='界面程序示例', $

    mBar = mBar , $

    uname ='tlb', $

    ;按行排列

    /COLUMN, $

   

    ;重设置大小时产生事件

    /TLB_SIZE_EVENTS,$

    ;关闭时产生事件

    /TLB_KILL_REQUEST_EVENTS)

  ;创建系统菜单

  wFile = WIDGET_BUTTON(mbar,value = '文件(&F)')

  wOpen = WIDGET_BUTTON(wFile, value = '打开(&O)')

  wExit  = WIDGET_BUTTON(wFile, value = '退出(&E)', $

    ;添加分隔线

    /Separator)

  ;创建一个按钮

  base2=WIDGET_BASE(base1,/row)

  label1=WIDGET_LABEL(base2,$

    value='当前事件:')

  text1=WIDGET_TEXT(base2, $

    xSize =10)

  button = WIDGET_BUTTON(base2,$

    value ='按钮', $

    uName ='button')

  mydraw=WIDGET_DRAW(base1,$

    retain=0,$

    ;设置大小

    xsize=400,$

    ysize=400,$

    ;滚轮时产生事件

    /wheel_events,$

    ;点击按钮时产生事件

    /button_events,$

    ;暴露(从遮挡到最前显示时)时产生事件

    /expose_events,$

    ;鼠标移动时产生事件

    /motion_events,$

    ;键盘敲击时事件

    /keyboard_events,$

    ;设置组件的uName,即名字。

    uname='mydraw')

  ;例示

  WIDGET_CONTROL, base1, /REALIZE

  ;创建右键菜单界面

  contextBase = WIDGET_BASE(mydraw, /CONTEXT_MENU)

  ;右键菜单中菜单选项

  button1 = WIDGET_BUTTON(contextBase, $

    VALUE='右键菜单1', $

    uname = 'contexButton1')   

  button2 = WIDGET_BUTTON(contextBase, $

    VALUE='右键菜单2', $

    uname = 'contexButton2')   

   

  ;获取系统初始化颜色模式

  DEVICE, Get_Decomposed = oriD

  ;显示伪彩色图像

  DEVICE, decomposed =0

  ;载入系统颜色表

  LOADCT,23

  ;显示一个400*400的方形图像

  imgData = DIST(400)

  TVSCL,imgData

 

  ;获取组件的大小信息

  sz = WIDGET_INFO(base1,/geom)

  drawSZ = WIDGET_INFO(myDraw,/geom)

  ;显示区域与主界面的边界间隔

  drawSpace = [sz.XSIZE,sz.YSIZE] - [drawSZ.XSIZE,drawSZ.YSIZE]

 

  ;创建结构体,包含各个组件ID和参数

  state={label1:label1,$

    contextBase: contextBase, $

    text1:text1,$

    oriD: oriD, $

    imgData : imgData , $

    drawSpace: drawSpace, $

    testStr  : '初始字符串!',$

    mydraw:mydraw}

  ;创建指针

  pstate=PTR_NEW(state,/no_copy)

  ;将指针信息存到tlbuvalue中保存

  WIDGET_CONTROL,base1,set_uvalue=pstate

  ;关联产生事件

 

  XMANAGER, 'WIDGET_EXAMPLES', base1, $

    cleanup = 'WIDGET_EXAMPLES_CLEANUP',/NO_BLOCK

;也可用这个方式:直接指定事件程序,event_handler ='abc'

   

END

 

另外对象使用时也可以用uValue,应用情形:如以浮点型数组,用IDLgrImage显示时数据会自动拉伸到byte型,再通过IDLgrImagegetProperty获取后为byte型数组,与浮点型相比的话精度会有所丢失。为了获取原数组值,可以用IDLgrImageuValue关键字对数据进行备份,当然,这种方式占用的内存对增大,如为了节省保存内存,可以将转换系数存储到uValue中,应用前后进行存储和读取运算。示例代码如下:


 

IDL> oriArr = dist(200)

% Compiled module: DIST.

IDL> print,max(oriArr,min = minV)

      141.421

IDL> print,minV

     0.000000

IDL> oImage = Obj_New('IDLgrImage')

IDL> oImage.SetProperty,data = oriArr

IDL> oImage.GetProperty,data = storeArr

IDL> print,max(storeArr)

 141

IDL> help,storeArr

STOREARR        BYTE      = Array[200, 200]

IDL> ;解决方法

IDL> oImage.SetProperty,data= oriArr,uValue = oriArr

IDL> oImage.GetProperty,data = storeArr,uValue = uArr

IDL> help,uArr

UARR            FLOAT     = Array[200, 200]

IDL> print,max(uArr)

      141.421

IDL> ;解决方法2,按线性函数公式y = k*x+b的格式,这样节省对象占用内存。

IDL> maxV = max(oriArr,min = minV)

IDL> ;计算转换系数

IDL> k = 255/(maxV-minV)

IDL> b = -minV/(maxV-minV)

IDL> ;存储原数组到oImage对象,系数到uvalue

IDL> oImage.SetProperty,data= oriArr,uValue = [k,b]

IDL> ;获取oImage对象中的数据和系数数组

IDL> oImage.GetProperty,data = storeArr,uValue = uArr

IDL> ;转换回初始数组

IDL> readData = uArr[0]*storeArr+uArr[1]

 

怎么查IDLgrImage的uValue参数呢。IDL的帮助中IDLgrImage的属性界面如下:

下面有继承基类名称:

点击链接进去,有继承基类的属性,继承基类的属性都可以在IDLgrImage中直接调用,当然也包含了uValue。





http://wap.sciencenet.cn/blog-344887-641954.html

上一篇:IDL的帮助文档字体修改方法
下一篇:C#调用IDL时传递参数或变量时字符串过长出错的解决方法

0

该博文允许注册用户评论 请点击登录 评论 (1 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2021-10-19 14:47

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部