IDL入门教程十二
- 格式:doc
- 大小:94.00 KB
- 文档页数:12
第十章编写简单的组件程序本章概述本章目的是演示如何通过使用组件开发工具包开发一个简单的、具有图形用户界面的IDL程序。
“组件”一词是指用来表示用户与程序输入输出交互作用的图形元素。
按钮、滑动条和文本框都是组件。
组件工具箱是一套IDL API命令的集合,它主要用于开发图形界面程序。
在本章中,将学到以下方面内容:1.组件定义模块和组件事件处理模块的区别;2.如何编写组件定义模块;3.如何编写组件事件处理模块;4.如何解释和理解组件的事件结构;5.如何创建不同类型的组件,比如顶层base组件,绘图组件和按钮组件;6.组件程序模块之间在不使用公共块的情况下如何传递信息;7.如何编写一个具有可改变大小的图形窗口的组件程序;8.如何向组件程序中添加简单控制按钮;组件程序的结构许多IDL程序(比如前一章的ImageBar程序)只是由单一的程序模块组成,而组件程序至少包含两个种程序模块。
组件定义模块是一个必不可少的程序模块,它可以是过程,也可以是函数。
组件本身的创建或定义就是在组件定义模块中进行的。
并且,还至少有一个事件处理模块(可以是过程也可以是函数),它对组件事件、触发器或用户的交互作用做出反应,并加以处理。
(请看下图81)甚至简单的组件程序也有几个事件处理模块,每一个模块都对不同的事件或触发器做出反应。
这就要求在事件处理模块和组件定义模块之间对程序的某些信息进行共享。
组件编程的主要技巧在于如何在构成组件程序或应用程序的各种程序模块之间传递程序信息。
图81 组件程序中的信息流从定义模块,通过事件结构传递到事件处理模块。
一般而言,定义模块只执行一次,而事件处理模块却是重复执行。
组件程序也被称为事件驱动程序,这意味着程序事先并不知道程序执行的顺序。
当用户对程序的组件元素进行交互作用时就会产生事件,然后事件处理模块根据事件产生的顺序分别对每个事件进行处理。
一般而言,组件程序的界面或可视部分在定义模块中产生,而组件程序的行为是在事件处理模块中产生。
IDL基础一.变量1.命名规则变量名称的最大长度不超过255个字符,变量的首位只能是字母和下划线,中后部只能是字母、数字、下划线“_”和连接符“$”。
2.创建变量变量有两个重要属性:数据类型和组织结构。
数据类型指出属于数据类型中的哪一种。
在IDL中有14种基本数据类型。
在图表1中可以看到每一种数据类型,每个类型创建的变量的字节大小、变量创建方式、数据类型之间强制转换的IDL函数名称。
除了数据类型外,一个变量有一个组织结构。
有效的组织结构有标量(例如单个数值)、矢量(真正的一维数组)、数组(最高可达八维)和IDL结构(能包含各种数据类型的变量和组织结构,结构中独立的组成部分称为字段)。
表1 : IDL中的14种基本数据类型3.IDL语言变量的特点创建IDL变量不需要事先声明,是通过赋值形式进行定义的语言变量定义。
并且变量随时可以进行数据类型和维数的动态改变。
IDL最强大的功能之一,就是大多数过程或函数都能在任何数据类型或组织结构上生效。
这是因为IDL在运行时能改变变量的数据类型和组织结构(像世界上其他强大的事物一样,这种动态改变变量的属性的能力也有潜在的巨大危险!必须小心,确信知道正在使用哪种数据)。
在IDL中,本质上讲变量是毫无意义的(像在Fortran或者C程序中),因为这种变量的数据类型很容易改变。
例如:IDL>num = 3 ; num是一个整型变量IDL>num = num*5.2 ; num变为一个浮点型变量变量num被初始化为一个整数,由于数学运算的结果和重新赋值,它被动态地改变成浮点数值。
这是因为IDL在数学计算当中为了保证最高的精度,将低精度的数据类型提升为高精度的数据类型。
当num 被再赋值(在等号的左边),它被提升为一个浮点数去保持等号右边计算的精度。
思考下面这个例子: IDL>result=4*x在这种情形下,不可能知道变量会产生哪种数据类型和组织结构,因为对x变量一无所知。
目录Part one:文件读写操作 (1)1、格式化输入与输出(read\print) (1)2、ASCII文件读写 (2)3、二进制文件读写 (5)4、图像格式文件读写 (7)5、科学数据格式读写*** (8)Part two:图形绘制 (11)(一)plot过程绘制 (11)(二)plotg()函数绘制 (12)(三)散点图 (12)(四)柱状图、条形图 (15)(五)绘制颜色条colorbar (18)Part three: ENVI二次开发 (20)1、自定义波段运算函数 (20)2、IDL中常见波段运算 (21)3、ENVI classic 创建自定义菜单 (22)4、ENVI classic+IDL 二次开发 (23)Part one:文件读写操作1、格式化输入与输出(read\print)1)Read:该函数用于从键盘键入数据,默认数据类型为浮点型,若要输入其他类型数据,需要先定义数据类型。
Eg:2)Print:该函数用于将数据输出打印到控制台,这里主要讲格式化控制输出format关键字。
2、ASCII文件读写常见ASCII文件:txt、matlab程序文件(*.m)、c程序文件(*.c)、遥感影像头文件(如ENVI 格式的头文件*.hdr)1)选择文件:fn = dialog_pick'选择ASCII文件:',get_path = work_dir)cd,work_dir ;用于跳转到当前工作路径2)查询文件:()函数Eg:查找当前工作路径下所有的txt文件,并返回文件数目*: (fname)函数用于查询文本文件的行数。
3)打开文件:在IDL中读写ASCII码或者二进制文件,首先需要将文件与一个逻辑设备号关联起来。
语法:openr/openw/openu, lun, fname, /get_lun, width=10,/append4)读写操作:IDL中利用readf函数读取文本文件、利用printf函数写入ASCII文件① Read f, lun, var01, var02….② printf, lun, var01, var02….5)文件关闭:在对文件操作完成之后,需要关闭文件的逻辑设备号,eg: freee_lun,lunEG:*如何获取某个文件你的列数:先读取一行数据,然后利用空格进行字符串拆分;最后利用n_elements()计算元素个数即为ns对于某些遥感数据的头文件前面几行是说明文件,后一部分才是数据的,读取有两种方式:1)定义一个临时变量temp,将说明文字用该变量存储2)直接跳行:skip_lun, lun, 3, /lines ;跳过文件的前三行3、二进制文件读写多数遥感数据的数据文件都是二进制文件。
IDL语言简明教程IDL(Interactive Data Language)是一种用于科学数据分析和可视化的专业编程语言,具有广泛的应用领域,包括天文学、地球物理学、气象学、生物学等。
IDL具有易于学习和使用的特点,本文将为您提供一个简明教程,帮助您快速入门IDL语言。
第一部分:IDL基础1.变量和数据类型-变量用于在内存中存储数据,可以用字母、数字和下划线命名,并区分大小写。
- 常见的数据类型包括整数(int)、浮点数(float/double)、字符串(string)和数组(array)。
2.数组和矩阵运算-数组是IDL中最常用的数据结构,可以存储一维或多维的数据。
-可以使用运算符进行数组的加减乘除运算,或进行矩阵运算。
-数组的索引从0开始,可以使用方括号指定索引值。
3.控制流语句- 控制流语句用于控制程序的执行流程,包括条件语句(if-else)和循环语句(for、while等)。
-条件语句根据条件的真假执行相应的代码块。
-循环语句用于重复执行一段代码,可以指定循环的次数或根据条件判断是否继续循环。
第二部分:IDL数据处理1.数据输入和输出- 使用read_*函数可以从文件中读取数据,如read_ascii、read_binary等。
- 使用write_*函数可以将数据写入文件,如write_ascii、write_binary等。
-IDL还提供了图形界面,可以通过鼠标交互进行数据的选择和操作。
2.数据处理函数-IDL提供了丰富的数据处理函数,用于对数据进行统计分析、滤波、插值等操作。
- 常见的函数包括mean、median、filter、interpolate等,可以根据具体需求选择函数进行数据处理。
3.图像处理和可视化-IDL可以进行图像处理和可视化,包括图像读取、显示、增强和保存等操作。
- 使用image_read函数可以读取图片文件,使用tv函数可以显示图像。
- IDL还提供了绘制2D和3D图形的函数,如plot、contour、surface等,可以将数据可视化。
IDL语言基础及程序设计IDL(Interface Definition Language)是一种用于定义软件组件接口的语言。
IDL语言基础包括数据类型、变量声明和赋值、运算符、流程控制等方面。
IDL支持多种数据类型,包括整数型、浮点型、字符串型等。
变量声明和赋值是IDL中常见的操作,用于给变量分配内存并赋予特定的数值或字符串。
IDL支持各种运算符,如算术运算符、逻辑运算符、比较运算符等。
流程控制方面,IDL支持条件语句和循环语句,可以根据条件选择执行不同的代码块,或者重复执行段代码。
IDL程序设计是利用IDL语言编写程序的过程。
以科学计算为例,IDL可以进行各种数值计算、矩阵运算、数据分析等。
IDL可以读取、处理和展示图像数据,支持各种图像处理算法和可视化方法。
IDL还可以进行数据可视化,绘制曲线图、散点图、等高线图、表面图等。
IDL还支持与其他编程语言的交互,可以调用其他语言编写的函数或者在其他语言中调用IDL编写的函数。
IDL程序设计的过程包括问题分析、算法设计、编程实现和测试调试。
首先,需要分析问题,明确程序的需求和功能。
其次,根据需求和功能,设计算法,确定程序的结构和流程。
然后,根据算法设计,编写程序代码,实现算法。
最后,对程序进行测试和调试,确保程序能够正确运行。
在IDL程序设计中,还可以使用IDL内置的函数和过程库来加快开发速度。
IDL提供了各种科学计算和图像处理功能的库,可以直接调用这些函数和过程来完成特定的任务。
例如,IDL内置了对数学函数、统计函数、线性代数函数等的支持,可以直接调用这些函数来进行数值计算和矩阵运算。
总之,IDL语言基础和程序设计涵盖了语言的基本语法和常用操作,以及利用IDL进行科学计算、数据处理和图像处理的方法。
通过学习和掌握IDL的基础知识和编程技巧,可以更高效地进行程序开发,并能够处理和分析各种数据和图像,满足科学研究和工程应用中的需求。
使用IDL的12个小技巧IDL(Interactive Data Language)是一种用于科学数据分析和可视化的编程语言,广泛应用于天文学、地球科学、气象学等领域。
下面列举了一些使用IDL的小技巧,以便更高效地使用该语言:1.使用多行注释:在IDL中,可以使用分号';'来添加注释。
然而,为了使代码更易读,可以使用/*注释内容*/的形式添加多行注释。
2.使用内建函数:IDL提供了许多内建函数来执行各种操作,如数学计算、数组处理、文件读写等。
在编写代码时,了解和使用这些函数可以有效地简化代码,并提高执行效率。
3. 显示帮助文档:IDL的帮助文档非常丰富,包括每个函数的定义、用法示例以及相关的参考资料。
在IDL命令行中,可以通过help函数来获取一些函数的帮助文档。
例如,help, function_name。
4. 使用通配符匹配文件名:在IDL中,可以使用*和?通配符来匹配文件名。
例如,read_ file, 'data*.txt'将读取以data开头、以.txt结尾的所有文件。
5.使用绘图模板:IDL提供了各种图形模板,可以用于创建各种类型的图表,如散点图、线图、柱状图等。
使用这些模板可以大大简化创建和自定义图形的过程。
6.使用图像处理工具:IDL提供了强大的图像处理工具包,可以对图像进行滤波、增强、分割等操作。
熟悉这些工具和函数,可以使图像处理过程更加高效和准确。
7. 使用结构体进行数据组织:IDL使用结构体(structure)来组织和存储复杂的数据。
结构体可以包含不同类型和大小的变量,使得数据的访问和操作更具有灵活性。
8.使用FOR循环和FOREACH迭代:在IDL中,使用FOR循环可以方便地对数据进行迭代处理。
另外,使用FOREACH迭代方式可以更加简洁地遍历数组元素。
9.使用条件语句:IDL提供了丰富的条件语句,如IF、ELSEIF和CASE语句,用于根据不同的条件执行不同的代码块。
idl教程第八章 IDL编程基础本章概述本章的目的是学习IDL基本编程技巧,具体的来说,可以学到以下方面内容:1.IDL批处理文件、主程序、过程和函数之间的区别;2.如何在IDL程序中输入和输出信息;3.如何在IDL程序中使用定位参数和关键字;4.如何编译和运行IDL程序;5.程序中的常用控制语句语法如果把IDL程序看作一系列IDL命令的话,那么IDL程序——或称为IDL程序模块——可以分为四类:(1)批处理文件(2)主程序(3)过程(4)函数。
编写IDL批处理文件最简单的程序是一个IDL批处理文件。
一个批处理文件由一系列命令组成,这与在IDL 命令行敲入的命令完全一样。
大多数人用批处理文件是为了自动执行自己在IDL命令行一次又一次敲入的命令。
例如,假设要在IDL中打开并显示一组图像,如果已经将图像数据读入到变量image 中,那么用来显示图像的命令可以如下所示:IDL> thisImage = BytScl (image, Top = 199)IDL>LoadCT, 5, NColors = 200IDL> s = Size (image)IDL> Window, /Free, XSize = s[1], ysize = s[2]IDL> TV, thisImage这五行代码并不多,但键入三、四次之后,可能已决定把他们放在一个名为ImageOut.pro 文本文件中。
这文件就是所谓的批处理文件。
要执行该文件中的命令,必须把@放在IDL命令行的开头,其后再加上文件名即可。
(.pro 为默认扩展名。
如果加了其它扩展名,那么应该把文件名称写完整)如下所示:IDL> @ImageOut 注意,文件名没有在引号中,这与IDL文件名的一般规则是不一致的。
IDL会严格执行批处理文件中的命令,就像在命令行上键入一样。
这意味着有必要用行续字符($)和其他命令行语言来让IDL确认键入的命令。
第三章编写IDL程序 (1)3.1 定义和编译程序 (1)3.1.1 过程 (2)3.1.2参数的继承 (4)3.1.2.1参数传值继承 (4)3.1.2.1参数传引用继承 (5)3.1.3 函数 (5)3.2 控制语句 (6)3.2.1 If 语句 (6)3.2.2 Case 语句 (7)3.2.3 for 语句 (7)3.2.4 While语句 (7)3.2.5 Repeat 语句 (8)3.2.6 Return 语句 (8)2.2.7 Goto 语句 (8)3.2.8 Switch 语句 (9)3.2.9 Break 语句 (9)3.2.10 Continue 语句 (10)3.4检测参数 (10)3.4.1 检测入口参数 (10)3.4.3检测布尔关键字 (11)3.4.4检测输出参数 (11)3.5脚本、包含文件和日志 (12)3.5.1 脚本 (12)3.5.2 包含文件 (12)3.5.3日志 (13)3.6 全局变量 (13)3.6.1 只读全局变量 (13)3.6.2 可写全局变量 (14)3.6.3 用户定义全局变量 (14)3.6.4 Common语句 (15)3.7 处理错误 (16)3.7.1 截取错误 (16)3.7.2 数学错误 (17)3.7.3 重设IDL工作期。
(17)第三章编写IDL程序3.1 定义和编译程序IDL 程序模块分为过程和函数。
3.1.1 过程过程是IDL中一类程序模块,句法:Pro Procedure_Name, argument1, ..., argumentN……任意多条语句End过程以Pro 语句开始,以End语句结束。
Pro语句至少含有一个过程名称,后跟若干个参数,可以没有参数。
1 过程的接口参数过程的接口参数称为形参,句法如下:PRO Procedure_Name, P1,P2,…Pn, Name1=Var1,Name2 = Var2, ….,NameN = VarN P1,P2,…Pn、Var1, Var2, …., VarN是过程的接口参数,用作变量名。
IDL语言简明教程IDL(Interface Definition Language)是一种用于描述计算机程序接口的语言。
它是一种中立的、面向对象的语言,被广泛用于定义接口的数据类型和操作,用以在分布式系统中进行通信。
IDL的主要用途是为不同语言和系统之间的通信提供统一的接口标准。
本文将提供一个简明的IDL语言教程,帮助读者了解IDL的基本概念和用法。
1.IDL的基本特性:-中立性:IDL是中立的,既不属于特定的编程语言,也不属于特定的操作系统。
这使得IDL能够在不同的系统和语言之间进行通信。
-面向对象:IDL支持面向对象的编程,支持类、继承、多态等概念。
-定义接口:IDL主要用于定义接口的数据类型和操作,通过IDL可以描述一个程序或模块提供的接口。
接口定义明确了接口的输入参数、输出参数以及可能抛出的异常。
-可扩展性:IDL支持扩展。
通过IDL,可以定义新的数据类型和操作,以适应不断变化的需求。
2.IDL的数据类型:-简单数据类型:IDL支持整型、浮点型、布尔型、字符型等简单数据类型。
-结构体:IDL支持结构体类型,可以通过结构体将几个不同的数据类型组合在一起。
-枚举型:IDL支持枚举类型,通过枚举类型可以定义一组预定义的常量。
-数组:IDL支持数组类型,可以定义一维、二维甚至多维的数组。
-字符串:IDL支持字符串类型,在IDL中可以使用字符串来表示文本数据。
3.IDL的操作定义:-输入参数和输出参数:IDL中的操作可以接受输入参数,并返回输出参数。
输入参数用于接收调用者传递给操作的值,输出参数用于返回操作的结果。
-异常处理:IDL支持异常处理机制,一个操作可以声明可能抛出的异常,调用者需要捕获并处理这些异常。
4.IDL文件的编写:-接口定义:IDL文件中通常包含一个或多个接口的定义,每个接口包含一组操作的定义。
- 导入模块:IDL文件中可以使用“import”语句导入其他模块中定义的接口和数据类型。
第十二章对话框程序本章概述本章主要讲解两种编写对话框程序的方法。
对话框是用于接收用户信息,并把信息传递到另一个程序模块,或程序中。
其中,将学到以下几个方面的内容:1.如何编写模式对话框;2.如何编写非模式对话框;3.如何在组件程序中用指针存储信息;4.如何在组件程序中使用伪消息;5.如何在独立的组件程序之间传递信息;创建模式对话框在上一章的XImageBar程序中,已经调用过一个模式对话框程序,即GetImage,它允许用户选择并读入一个影像文件。
在XImageBar程序中,这个对话框被调用过两次。
一次是在组件定义模块中,当一个影像数据未被传入到程序时;另一次则是在Open Image按钮被按下的时候。
(如果在上一章中没有编写XImageBar程序,可以调用与本书配套使用的文档XImageBar.9.pro。
)在第一个程序实例中调用方式如下:image = GetImage (Cancel = canceled)在第二个程序实例中调用如下:image = GetImage (Cancel = canceled, Parent = event. Top)在这两次调用过程中有几个微小的区别,不过调用时读者可能没有注意到。
如果想编写对话框程序,就必须了解这两次调用的差别以及它们是如何工作的。
阻塞的组件程序在上述例子中,第一次调用GetImage时,GetImage程序运行时就好比是阻塞的组件程序。
要看它是如何工作的,在IDL命令行中键入如下所示:IDL > image = GetImage ( )注意到IDL命令行要么是消失了要么是变灰了。
这时要在IDL命令行上键入命令并执行它们是不可能的。
我们就称IDL命令行是阻塞了。
(当命令行正处于消失或变灰状态时,可以键入命令,但只有在命令行解除了阻塞后命令才可以执行。
)一般而言,无论运行哪一种IDL程序都会阻塞IDL命令行。
换言之,只有等到当前的命令执行完毕后才有可能键入并执行另一命令。
【167】IDL中相关技巧IDL 中相关技巧1. 注释:分号“;”表⽰注释内容的开始。
2. 续⾏:最后⼀个字符是“$”,那么本⾏将紧接着下⼀⾏,续⾏标志。
(换⾏符,$+回车)3. 中⽂编码:窗⼝》⾸选项》常规》⼯作空间》⽂本⽂件编码 【GB2312】中⽂编码4. ⼯作空间:⽂件》切换⼯作空间【也可以通过复制⽂件夹,然后在左侧粘贴即可】5. ⼤⼩写:窗⼝》⾸选项》IDL》格式器 === 修改⼤⼩写,通过Ctrl+Shift+F 变⼤写(改变成默认格式)=== 通过9的⽅法也可以修改成Alt+F 总结: Step 1:⾸先修改格式器中全部为⼤写! Step 2:修改格式快捷键,缺⼀不可!6. 帮助:快速获取帮助,"?indgin"7. 显⽰命令⾏:窗⼝》显⽰视图》其他,勾选“命令⾏”8. 多⾏注释:Ctrl+;可以注释多⾏9. 补全函数:Alt+/可以补全 可以修改快捷键如下图所⽰:10. 消息窗⼝:DIALOG_MESSAGE函数11. 断点:双击增加“断点”,点击F6往下⾛12. 中⽂错误:print 某些中⽂字的时候(例如"程序"),会出现语法错误,前⾯加上⼀个空格就好了,或者不⽤双引号,⽤单引号!13. 程序发布:⾸先重置下,命令⾏中输⼊:save, filename='D:\helloidl.sav', /routines,⽣成*.sav⽂件14. 可执⾏程序:命令⾏中输⼊:make_rt, 'helloidl', 'D:\', savefile='D:\helloidl.sav', /overwrite,⽣成*.exe⽂件,通过修改“helloidl.ini”中的“Show=False”,同时将ENVI的License⽂件夹复制过去可以将两个提⽰关掉,直接显⽰代码内容15. 快速获取⽂件路径:直接拖拽过去即可16. 调出“命令⾏”的⽅法17. 修改代码字体:18. 添加⼯程项⽬:右键 >>> 新建⼯程 >>> 选择“从已存在⽬录创建IDL⼯程”SYSTIMEN_ELEMENTSN_PARAMSKEYWORD_SETARG_PRESENTS。
第十二章对话框程序本章概述本章主要讲解两种编写对话框程序的方法。
对话框是用于接收用户信息,并把信息传递到另一个程序模块,或程序中。
其中,将学到以下几个方面的内容:1.如何编写模式对话框;2.如何编写非模式对话框;3.如何在组件程序中用指针存储信息;4.如何在组件程序中使用伪消息;5.如何在独立的组件程序之间传递信息;创建模式对话框在上一章的XImageBar程序中,已经调用过一个模式对话框程序,即GetImage,它允许用户选择并读入一个影像文件。
在XImageBar程序中,这个对话框被调用过两次。
一次是在组件定义模块中,当一个影像数据未被传入到程序时;另一次则是在Open Image按钮被按下的时候。
(如果在上一章中没有编写XImageBar程序,可以调用与本书配套使用的文档XImageBar.9.pro。
)在第一个程序实例中调用方式如下:image = GetImage (Cancel = canceled)在第二个程序实例中调用如下:image = GetImage (Cancel = canceled, Parent = event. Top)在这两次调用过程中有几个微小的区别,不过调用时读者可能没有注意到。
如果想编写对话框程序,就必须了解这两次调用的差别以及它们是如何工作的。
阻塞的组件程序在上述例子中,第一次调用GetImage时,GetImage程序运行时就好比是阻塞的组件程序。
要看它是如何工作的,在IDL命令行中键入如下所示:IDL > image = GetImage ( )注意到IDL命令行要么是消失了要么是变灰了。
这时要在IDL命令行上键入命令并执行它们是不可能的。
我们就称IDL命令行是阻塞了。
(当命令行正处于消失或变灰状态时,可以键入命令,但只有在命令行解除了阻塞后命令才可以执行。
)一般而言,无论运行哪一种IDL程序都会阻塞IDL命令行。
换言之,只有等到当前的命令执行完毕后才有可能键入并执行另一命令。
IDL 5以前的版本中,所有的组件程序也都是如此运行的。
一旦运行了一个组件程序,只有等到这个组件程序执行完毕后才可进入IDL 命令行。
但在IDL5中,刚才的现象已经改变了。
现在,可以运行一个组件程序并立即在IDL 命令行上输入命令然后执行它。
我们称这种组件程序为无阻塞组件程序。
要创建一个无阻塞的组件程序,只需要程序中的XManager 命令使用关键字No_Block即可。
这正如先前编写的程序XimageBar中所做的那样。
然而,在程序GetImage中的XManager命令是没有关键字Bo_Block的。
因而,它是一种阻塞程序。
在这里的“阻塞”,是指在执行Xmanager命令的同时,IDL就停止执行GetImage组件定义模块中的代码。
组件定义模块中任何在XManager命令下面的代码(其中也有一些可以,待会可以看到)都不能被执行,直到组件程序被销毁后才被执行,也就是说这是阻塞被解除了。
这对像GetImage这样的程序是合适的,因为阻塞给用户提供了足够的时间来填写表格或对话框中的信息。
当用户添完表格,他们就会点击Cancel或Accept按钮。
无论哪种情况,IDL都将销毁组件,并解除阻塞,程序也可以用所收集的信息继续工作。
对于GetImage而言,收集的信息是指关于数据文件、打开文件读取数据,将结果返回给用户。
所有收集,读取,返还这一系列的操作都是在组件定义模块中的XManager命令执行完毕后才进行。
优点就这些。
但是,阻塞也有个细微方面容易被忽视。
那就是,只有第一个调用XManager 为阻塞的组件程序才可以成为阻塞。
后来所有的组件程序都将越过阻塞好像他们是无阻塞的组件程序一样。
这种行为对于像GetImage这样的程序而言,完全是一个灾难,因为程序将在用户获得填写表格的机会之前就开始读取数据文件。
从一个自己对它一无所知的文件中读取数据会带来一些小麻烦。
模式组件程序如果想确保在任何条件下一个组件程序都会阻塞,而不是仅仅在第一次侥幸地调用Manager后才成为阻塞,那么就必须建立一个模式的组件程序。
模式的组件程序总是在执行XManager命令时处于阻塞状态,直到组件被销毁。
在IDL5以前的版本中,编写一个模式的组件程序相对简单些。
只要简单地在XManager 命令后设置关键字Modal即可。
但在IDL5中,Xmanager命令中的关键字Modal已经被废弃了。
取而代之的是,在创建顶级base时的Widget_Base函数中增加一个Modal关键字。
这里有一个很小却很重要的补充。
如果为一个base组件设置Modal关键字,同时也必须为那个base组建设置一个有效的Group Leader(通过设置Group_Leader关键字)。
这对要编写一个既能在IDL命令行中运行,又能在程序中运行的对话框程序的难度就更大了。
等一会编写程序时或许就会明白这个意思了。
编写模式对话框的定义模块程序GetImage是一个对话框程序的绝好例子,但也是相当复杂的。
如果是从一个更简单的例子开始,那么就能够更容易理解创建对话框的规则。
由于在与本书配套使用的文档下的Coyote目录中,有许多类似2D字节数组的数据文件,那我们就从编写一个简单对话框程序开始,用于打开和读入Coyote目录下的文件。
通过调用这个程序,就可以获得这个文件的名字以及在X和Y方向上的大小,暂且称这个程序为GetData吧。
Coyote目录下的数据文件以及文件大小的详细信息请参阅313页的“附录B:数据文件描述”。
如果希望让用户将某些信息输入到表格中,一般来说,这办法不是很好,如果我们对用户一点也不了解的话,或许他们就无法输入。
如果可能的话,让用户选择一个文件名或用鼠标点击选择文件的大小将会是个更好的主意。
假定确实要让用户输入,那么让用户输入的越少越好。
解决上述问题一种方法就是,在输入框内提供一些默认值,这些值可能是对的,因此用户也不需要输入。
同样,也希望在程序调用时用户能够指定一个文件名或文件的大小。
因此,如下打开一个文本编辑窗口,将对话框的定义语句定义如下:Function GetData, filename, XSize = xsize, YSize = ysize, $Cancel = cancel, Parent = parent关键字Cancel是一个输出型变量,它用来标示是对话框中的Cancel按钮还是Accept 按钮被按下了。
关键字Parent包含了模式组件程序的GroupLeader的标示符。
(喜欢关键字Group_Leader的名字吧)记住在定义模式的base组件时必须有Group Leader。
接下来,决定程序在出现错误时怎么处理(作者喜欢将程序控制返回给调用者),以及在没有提供关键字时设置关键字的默认值。
增加如下所示:On_Error, 2; Return to caller.IF N_Elements(filename) EQ 0 THEN $filename = Filepath (Root_Dir=Coyote(), ‘ctscan.dat’) ELSE $filename = Filepath (Root_Dir=Coyote(), filename)IF N_Elements (xsize) EQ 0 THEN xsize = 256IF N_Elements (ysize) EQ 0 THEN ysize = 256这里的Coyote命令是用于查找Coyote目录的。
如果这个目录存在,那么Coyote目录将是默认的路径,否则将在当前的目录中查找文件。
Filepath命令将返回一个与设备无关的文件名称。
默认的文件为ctscan.dat,一个有256X256的字节数组。
接着,定义对话框的偏移值,时的它定位于屏幕的中心,键入如下:Device, Get_Screen_size = screenSizeXCenter = FIX (screenSize [0] / 2 . 0)YCenter = FIX (screenSize [1] / 2 . 0)Xoff = xCenter - 150Yoff = yCenter – 150定义一个顶级的模式base接下来的就是为这个模式对话框创建一个顶级的base。
在定义一个定级的模式base必须有一个有效的Group Leader,这在前面已经强调了多次。
如果把一个Group Leader通过关键字Parent传递给程序,那将没什么问题。
但事实并非总是如此。
例如:如果用户想在IDL 命令行中调用该程序,一般来讲,这是不不太可能获得一个有效的Group Leader的。
没有有效的Group Leader,因而就不得不依赖它是一个阻塞组件。
再者,如果在IDL命令行上第一次调用Xmanager,这个程序将会阻塞,这时再调用程序也不成问题。
当Group Leader没有定义或者程序GetData的调用者是它自己本身时,程序就会出现麻烦了。
作者也不清楚该如何走出这进退两难的境地。
更让我不喜欢的是,在另一个程序中如果要正确调用该程序,参数Group Leader就是必不可少的。
此外,当在IDL命令行调用它时,Group Leader参数就不应该是一个必须的参数。
不管如何,如果指定了Group Leader,就可以创建顶级的模式base。
如果没有指定Group Leader,那么只有指望在IDL命令行上调用该程序了,如下所示:IF N_Elements (parent ) NE 0 THEN $Tlb = Widget_Base(Column =1 , Xoffset = xoff, Yoffset = yoff, $Title = ‘Enter File Information…’, /Modal, $Group_Leader=parent, /Floating, /Base_Align_Center ) Else $Tlb=Widget_Base(Column=1, Xoffset=xoff, Yoffset=yoff ,$Title=’Enter File Information…’, /Base_Align_Center)注意,设置在顶级的模式base上的关键字Floating。
一个浮动组件总是浮现在Group Leader程序之上。
这可以防止程序隐藏在其他窗口之后。
关键字Base_Align_Center确保顶级base的子组件在顶级base中以居中方式对齐。
定义其他组件定义一个子base,来包含文件名域和文件大小域。
子base并不是真的需要,但使用子base可以将在窗体周围设置一个框,并把它与窗体底部的按钮分隔开来。