操作系统  办公  实用知识  设计  开发  WEB开发  移动开发  数据库  软件工程  网管  安全  管理  信息化  答疑  渠道 

使用布局管理器 呈现生动的JAVA程序界面

2003-10-19 网友评论 0 条 点击进入论坛

如果你曾经为文本模式的应用程序设计过用户界面,那么你就会熟悉其中所涉及的问题。你需要获得每个标签、菜单、输入字段以及其他修饰元素,再把它们放到屏幕上显示,还要考虑每个东西的尺寸以及屏幕的尺寸。由于所有这些参数都是提前知道的,所以一些简单的算法就能够很好地完成这项工作。

但是,相同的情况却不会发生在图形应用程序上,因为每个元素最佳的尺寸和位置都依赖于多个因素,而这些因素在编辑的时候常常是不可知的,例如屏幕的分辨率、窗口和字体的大小等等。这就不可能手动计算其位置和尺寸了。

Java运用了一个原始的解决方案来解决这个问题——布局管理器,它能够让你只使用Java代码(不需要使用可视化工具)就设计出复杂的适合任何屏幕分辨率和尺寸的用户界面。

现在让我们来看一下布局管理器,看它们是如何工作的,以及如何创建自定义的布局管理器的,这样你就能够在必要的时候有效地使用那些Java平台自带的布局管理器,或者开发你自己的。我会假设你已经熟悉了AWT和/或Swing。

 

概述

 
布局管理器是一个对象,其唯一的任务就是将组件安放(也就是说,确定其尺寸和位置)进一个容器里(container)。每个容器都有一个java.awt.Container的子类,并提供一个方法——setLayout,用来指定要被使用的布局管理器。

在通常情况下,容器已经被指定了一个缺省的布局管理器,而且如果没有正确设置的话还可以通过setLayout来更改。而其他的东西则要使用一个专用的布局管理器,它们就不能够或者不应该被更改了,例如java.awt.ScrollPane和javax.swing.JRootPane。

布局管理器必须要实现java.awt.LayoutManager或者java.awt.LayoutManager2这两个接口。Java平台已经自带了很多布局管理器,所以你需要做的就是将正确的类实例化,再调用容器的setLayout,同时传递最新创建的布局管理器。

你甚至能够完全不使用布局管理器(例如将null传递给setLayout),但是在这种情况下,你必须使用java.awt.Component的正确方法(例如,setBounds、setLocation和setSize)来手动指定每个组件的位置和尺寸。

使用布局管理器

 
理解布局管理器是如何工作的最好方法是研究例子。Listing A里是一个非常简单的程序,它使用java.awt.BorderLayout布局管理器(也就是说,框架所缺省的布局管理器)来创建一个java.awt.Frame,并用一些按钮来填充它——每个BorderLayout区域内都有一个,BorderLayout.WEST这个区域除外,因为它由java.awt.Panel面板组件来填充。这个面板也会使用BorderLayout,并用按钮来填充。

运行这个程序的结果就是图A里的窗口。这都是java.awt.Window.pack方法的魔力。当这个包装方法被调用的时候,它就使用其首选的尺寸为窗口提供尺寸,这个首选的尺寸是由getPreferredSize方法返回的。

图A

一个简单的窗口首选尺寸

当getPreferredSize方法被调用用于某个组件的时候,它就会为这个组件返回最佳的尺寸(在按纽的情况下,这个尺寸就是在考虑到字体以及额外的空间和边界的大小之后,按钮标签的大小),但是当它为容器而被调用的时候,布局管理器就被调用,以计算其最佳的尺寸。

用于每个组件的布局管理器叫做getPreferredSize,它会使用某种算法(具体是哪种算法要依赖于布局管理器)来计算最终的尺寸。如果一个组件自身就是容器,那么这个进程就被循环使用。其最终的结果是,每个组件都获得了足够的空间以能够正确地显示。

一旦窗口的尺寸被给出,布局管理器就会被调用,以安置这些组件。这一次,由于尺寸已经被确定了,所以布局管理器只需要根据组件自己的逻辑和可用空间就可以给组件指定位置和尺寸了。

每当容器的尺寸发生改变或者影响其尺寸的某个组件的属性发生更改时,布局管理器也会再次被调用以安置这些组件。如果你重新改变示例程序的窗口尺寸,那么按纽也会相应地被重新安置。

如果你点击一个按钮,其字体的尺寸就会增大一倍,这会增加按钮标签的大小,并使得按钮自身也增大,最终这个窗口的布局就会像图B里的窗口一样。

图B

重新指定窗口和组件的尺寸
创建一个自定义的管理器
 
使用Java平台所提供的布局管理器,或者将它们组合起来使用,你就能够真正地实现任何布局。但是,这些所提供的布局管理器在有些情况下仍然不能满足你的要求。如果这种情况发生了,那么解决的方法就是创建你自己的自定义布局管理器。
幸运的是,创建一个布局管理器并不困难。如果你的布局管理器需要一些限制条件的话,你所需要做的就是去实现java.awt.LayoutManager或者java.awt.LayoutManager2这两个接口。表格A和表格B提供了每个接口的完整描述。
方法 描述
addLayoutComponent(String,Component) 向布局管理器添加组件,同时将它同给定的字符串相关联
layoutContainer(Container) 安置给定容器的组件
minimumLayoutSize(Container) 在考虑其组件(的大小)的同时,计算容器的最小尺寸
preferredLayoutSize(Container) 在考虑其组件(的大小)的同时,计算容器的首选尺寸
removeLayoutComponent(Component)               从布局管理器里清除给定的组件
表格A:LayoutManager接口
 
方法 描述
addLayoutComponent(Component,Object)           向布局管理器添加组件,同时将它同给定的限制条件相关联
getLayoutAlignmentX(Container) 返回容器的水平校准
getLayoutAlignmentY(Container) 返回容器的垂直校准
invalidateLayout(Container) 取消布局管理器已经对容器所缓冲的任何信息的有效性
maximumLayoutSize(Component) 在考虑其组件(的大小)的同时,计算用于容器的最大尺寸
表格B:LayoutManager2接口
Listing B里显示了一个自定义布局管理器的简单实现——ProportionalGridLayout。ProportionalGridLayout会将组件放置到一个在构建的时候就指定了的单元格网格里。每个单元格所占有的空间都是同其行和列的尺寸成比例的。
Listing C是一个显示实际使用的ProportionalGridLayout的简单例子。它创建了一个由ProportionalGridLayout来管理的框架,这个框架带有三行和三列,并由按钮来填充。运行这个例子就会出现图C的结果。由于每个按钮基本上都是同样大小的,因此所有的行和列都具有相同的尺寸。
图C

一个自定义的布局管理器的例子
如果窗口的尺寸增加了,而且有一个按钮被点击了(其字体的大小会增大一倍),那么其行和列就会按比例获得比其他行和列更多的空间,如图D所示。
图D
自定义的布局策略
ProportionalGridLayout的核心就是getColWidth和getRowHeight这两个方法,它们会分别返回给定列的首选宽度以及给定行的首选高度。首选的宽度/高度是通过对给定列/高度的所有单元格进行迭代,并返回最大首选宽度/高度值来计算得出的。
有了这些方法,要实现preferredLayoutSize就很简单了。它只需要计算出所有列和行的首选尺寸的总值,再加上容器的边界大小,就能够返回结果了。
layoutContainer方法的实现稍稍复杂一点,但是同样很简单。它只是将列之间的容器宽度按比例地分配成为每个列的首选宽度,将容器的高度按比例地分配成为每个行的首选高度。最后一列和和最后一行是个特例,它获得了剩余的空间以避免由浮点不精确所造成的差错。
由于ProportionalGridLayout没有使用限制条件,因此addLayoutComponent和removeLayoutComponent什么也没有做。要保持这个例子的小巧,我没有去实现一直会返回(0,0)的minimumLayoutSize方法,但是其逻辑和preferredLayoutSize方法是相同的,不过这只是相对于每个列/行的最小尺寸而言的。
 
复杂界面
布局管理器的概念允许创建复杂的用户界面,这只需要一定量的Java代码,而不需要可视化的工具。所生成的用户界面能够有效地独立于平台、屏幕大小和分辨率。
理解布局管理器的内部机制不仅对于开发满足特殊需求的自定义布局管理器很重要,而且对于更好地使用Java平台所提供的布局管理器也是很重要的。看一看Java 2 SDK API的规范就会获得更多关于布局管理器的细节信息。
已有 0 位对此文章感兴趣的网友发布了看法    
我来评两句 登录邮箱: 密码:
  匿名发表
今日推荐
技术文库(共有 46430 篇文章)
操作系统
办公软件
实用知识
网络管理
软件开发
WEB开发
软件工程
数据库
设计在线
信息安全
行业信息化
管理信息化
重点推荐
电子杂志订阅
点击电子杂志名称查看样刊
输入E-mail地址即可订阅
E-mail