IDL如何编写一个对象图形系统(4)

2018-12-27 16:37

图5-3:重新执行图形指令后改变了尺寸的窗口

在IDL绘制组件中用直接绘图法也会产生同样的问题。还好,我们只需重新执行原来的图形指令就可在当前尺寸的窗口中正确显示图形。 IDL不会将一般的图形窗口尺寸的改变通知程序。不过我们可对顶层基底作出设置使之能接收尺寸变化事件。这样此顶层基底下的绘制组件就会随之改变大小并重绘其内图形。如果图形必须是可变尺寸的,就需要编写一个组件程序。

改变大小事件

可变尺寸的图形窗口是一个绘制组件,其顶层基底会生成改变尺寸事件,触发此类事件时,内部的绘制组件就会改变大小并重绘其内图形。

默认状态下,顶层基底是不会生成尺寸变化事件的,因此必须要设置TLB_SIZE_EVENTS关键字。打开plotinteractive.pro文件并对PLOTINTERACTIVE做如下黑体部分改动: Plotinteractive

; Create the top-level base – add resize events. Tlb= widget_base(title='Interactive plot', /column, $ /tlb_size_events)

我们不应该通过EVENT_PRO关键字为顶层基底而应借助于XMANAGER来指定事件处理器。改变尺寸事件处理器需要绘制组件的组件标识和控制基底,将这些信息放入状态结构体中。

; Create a structure of data for the application.

State={data:data, win_id:win_id, linestyle:0, psym:0,$ connect:1,controlbase:controlbase,draw:draw}

; create a pointer to the state structure and put that pointer ;into the user value of the top-level base.

pstate = ptr_new(state, /no_copy)

Widget_control, tlb, set_uvalue=pstate

16

; Draw a plot by calling the \plotinteractive_doplot , pstate

; Call xmanager to start the event handling process. Xmanager,'plotinteractive',tlb,$

event_handler='plotinteractive_resize'

我们用XMANAGER的EVENT_HANDLER关键字为顶层基底设置事件处理器。下一步是要写出改变尺寸事件处理器PLOTINTERACTIVE_RESIZE。 Plotinteractive_resize

Pro plotinteractive_resize, event

Widget_control, event. top, get_uvalue=pstate

; To properly resize a draw widget, the geometry of the bases ;surrounding it must be determined and subtracted. statusg = widget_info((*pstate).status, /geometry)

controlg = widget_info((*pstate).controlbase, /geometry) tlbg = widget_info(event. top, /geometry)

; Subtract out the xpadding of the tlb for the xsize newx=event.x-2*tlbg.xpad

; Subtract the ysize and ypadding of the xaize.

newy = event.y – statusg.scr_ysize – controlg.scr_ysize $

- 2*(statusg.ypad + controlg.ypad + tlbg.ypad)

; Resize the draw widget.

Widget_control, (*pstate).draw, xsize=newx, ysize=newy

; Call the “do” routine to replot the graphics. Plotinteractive_doplot,pstate end

组件的几何结构

PLOTINTERACTIVE_RESIZE不可缺少的一部分是用带GEOMETRY关键字的WIDGET_INFO函数取得该组件的几何结构。从GEOMETRY返回的值是一个状态结构体,其中记录着该组件的各种尺寸和填充状态,这些都将作为位置参数传入WINDGET_INFO。所有组件在边缘处都有填充,某些组件还有与程序员所设尺寸不同的屏幕尺寸(SCR_[XY]SIZE关键字)。触发改变尺寸事件时,XMANAGER会传递含有顶层基底的新尺寸的事件结构体。为了恰当地改变组件尺寸,就必须在顶层基底中扣除绘图组件周围的其他组件的尺寸。上述代码扣除了绘制组件上下方其他组件的屏幕尺寸和填充。一旦成功地改变了绘制组件尺寸,就会调用“do”例程在新尺寸的绘制组件中重绘图形。

绘制组件的交互

在图形区域移动,按下或释放鼠标时,绘制组件就会生成事件。这些事件允许用户与显示在

17

绘制组件中的图形进行交互,可实现交互式标注及实时显示鼠标位置等功能。

在绘制组件中用鼠标实现交互不是自动完成的。默认状态下,IDL绘制组件不会生成任何事件。我们必须在创建绘制组件时就告诉它要生成鼠标事件。 Plotinteractive

; create the top-level base-add resize events.

tlb=widget_base(title='Interactive plot', /column,/tlb_size_events) status=widget_label(tlb,value=' ',/dynamic_resize)

; create a draw widget.

Draw = widget_draw(tlb, xsize=500, ysize=200,$ /motion_events,event_pro='plotinteractive_draw')

; create a row base to hold a series of controls. Controlbase = widget_base(tlb,/row)

上述代码中对组件创建例程做了两处补充。其一是一个标签组件,用它在绘制组件中显示鼠标位置。其二是为WIDGET_DRAW添加了一组关键字,通知IDL生成鼠标移动事件并将这些事件传送到事件处理器PLOTINTERACTIVE_DRAW。

在为绘制组件编写事件处理器前,必须在状态结构体中添加标签组件的标识status。 Plotinteractive

; Create a structure of data for the application.

State={data:data, win_id:win_id, linestyle:0, psym:0,$

connect:1,controlbase:controlbase,draw:draw,status:status} 对标签组件作出任何改动时都需要用到组件标识。绘制组件的事件处理器会在鼠标移动时更新状态标签。

Plotinteractive_draw

Pro plotinteractive_draw, event

;Retrieve the state pointer from the top-level base user value. widget_control, event. top, get_uvalue=pstate

;Enter the following block when a motion event occurs. If (event. type eq 2) then begin

; Convert the event coordinates from device to data.

Datac = convert_coord(event.x, event.y, /device, /to data) ;make a string variable from the coordinates of the mouse. Statusstr = strtrim(datac[0],2) + strtrim(datac[1],2) ;Set the string as the value of the label widget.

Widget_control, (*pstate).status, set_value=statusstr Endif End

绘制组件的事件结构体

一个绘制组件的事件处理器必须能够处理各种可能的事件组合。绘制组件的事件结构体是所有事件结构体中最复杂的。结构体定义如下:

event={wedget_draw,id:0L,top:0L,handler:0L,type:0,x:0,y:0,$ press:0B,release:0B,clicks:0}

id,top和handler域是每个组件的标准域(见前述的“事件结构体”一文)。其他域的描述如

18

下:

event.type 表明发生的事件类型。0=按下按钮,1=释放按钮,2=移动,3=改

变视点,4=显示(exposure)。

event.x,event,y 鼠标事件发生时在设备坐标中的x和y坐标。 event.press 若触发了按下按钮事件(类型0),此域将列出按下的鼠标按钮。1=

左按钮,2=中间按钮,4=右按钮。

event.release 若触发了释放按钮事件(类型1),此域将列出被释放的鼠标按钮。1

=左按钮,2=中间按钮,4=右按钮。

event.clicks 此域将显示鼠标的点击次数,0,1或2。

事件处理器PLOTINTERACTIVE_DRAW用type,x和y域获取鼠标位置并更新状态标签。编译并测试应用程序。

改变图像尺寸

可变大小组件程序的用途之一是显示图像。在IDL直接绘图例程如PLOT, SURFACE, 和CONTOUR中发生改变尺寸事件时,所得图形会自动适应新窗口的尺寸。这与用TV或TVSCL过程显示图像不同,对于这些例程而言,图像数据必须依某种方式按比例转换到新窗口的尺寸内。

JPEGVIEW程序

我们将在这里创建一个程序,用它在绘制组件中显示图像并在用鼠标改变窗口尺寸的同时改变图像大小。此程序的设置允许用户选择一个8位索引文件或一个24位的象素间隔格式的JPEG图像。下面首先给出了JPEGVIEW程序的创建例程: jpegview

pro jpegview

;Retrieve the visual depth of the display and the current IDL ; color mode, as well as the color table, if allowed. device, get_visual_depth=vd

device, get_decomposed=odec if odec eq 0 then begin tvlct, r, g, b, /get loadct, 0, /silent

endif else r = ( g = (b = 0))

依此代码,IDL可确定显示颜色的数目并根据情况运行颜色索引模式或颜色分解模式。若IDL在颜色索引模式下运行(odec=0),则原始颜色表存储在三个变量中并会加载灰度颜色表(颜色表0)。 jpegview

; Use DIALOG_PICKFILE to select a JPRG image file. jpeg_file = dialog_pickfile (filter = '*. jpg', / fix_filter) if jpeg_file eq '' then return

; Use QUERY_JPEG to get information about the selected ; image file .

19

ok = query_jpeg(jpeg_file, jpeg_fileinfo) if ok eq 0 then return

用DIALOG_PICKFILE找出并选择要读取的JPEG文件。若未选中文件则退出程序,若选中文件则完整的文件路径将以字符串格式返回到变量jepg_file。用QUERY_JPEG函数测试jepe_file是否的确含有有效的JPEG图像,若是返回1,否则返回0。QUERY_JEPG函数也可返回一个含有图像相关信息的结构体变量。这里此结构体将返回到变量jpeg_fileinfo。 jpegview

; Read the contents of the JPEG file into an IDL variable. if vd le 8 then begin

read_jpeg, jpeg_file, image_data, colormap,$

colors=!d.table_size, /dither, /two_pass_quantize tvlct, colormap

jpeg_fileinfo.Channels = 1

endif else read_jpeg, jpeg_file, image_data

用READ_JPEG过程读取JPEG文件。若运行IDL的电脑只能显示8位或更少的颜色(vd=8),则不能用它显示24位的分解图像。不过,READ_JPEG的内置功能可量化颜色分解后的图像,用颜色表显示此类图像。

下一步为JPEGVIEW构建组件层次构架。 jpegview

; Construct a widget hierarchy with a top-level base and a ; draw widget.

tlb = widget_base (title='JPEG Viewer │' + jpeg_file, /column,$ /tlb_ize_events )

draw = widget_draw(tlb ,xsize=jpeg_fileinfo.Dimensions[ 0 ] , $ ysize=jpeg_fileinfo. Dimensions[ 1 ]) widget_control , tlb , / realize

widget_control , draw , get_value=win_id

此时的组件层次构架仅由顶层基底和绘制组件组成。最初的绘制组件具有原始图像的维数。在PLOTINTERACTIVE中为顶层基底设置TLB_SIZE_EVENTS关键字将会在其尺寸改变时触发事件。 jpegview

; Store useful information in a state structure. state = { $

odec : odec , $

r : r , g : g , b : b ,$

is_truecolor: ( jpeg_fileinfo . channels gt 1), $ win_id:win_id, $ draw:draw, $

image:ptr_new(image_data), $

imagecopy:ptr_new(image_data , /no_copy)}

;Store the state structure in heap memory (global) and

20


IDL如何编写一个对象图形系统(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:给水排水管网系统期末考试复习资料整理(完整版)

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: