我们都知道,java GUI的界面定义是由awt类和swing类来完成的。它在布局管理上面采用了容器和布局管理分离的方案。也就是说,容器只管将其他小件放入其中,而不管这些小件是如何放置的。对于布局的管理交给专门的布局管理器类(LayoutManager)来完成。
其实,java在GUI方面应该是并不成功的.Awt类和swing类的结构非常复杂,加上充斥其间的子类继承和接口实现,使得要想掌握这两个类非常困难。这也是很多的java程序员抱怨的事情,但GUI已经成了程序发展的方向,所以这里我们也得勉为其难了。
现在我们来看java中布局管理器的具体实现。我们前面说过,java中的容器类(容器),它们只管加入小件(元),也就是说,它只使用自己的添加()方法向自己内部加入小件。同时他记录这些加入其内部的小件的个数,可以通过container.getComponentCount()方法类获得小件的数目,通过container.getComponent (i)来获得相应小件的句柄,然后LayoutManager类就可以通过这些信息来实际布局其中的小件了。
java已经为我们提供了几个常用的布局管理器类,例如:BorderLayout, FlowLayout, GridBagLayout等等。但在实际的布局上,我们还是会有其他的需要。我在不久前的一个问题中曾经要一个垂直的流式布的局,我称之为VflowLayout,其实BoxLayout和GridBagLayout可以完成类似的工作,但前者是swing类的成员,我的客户端是一个applet,不能使用,而后者必须在类生成的时候指定列数,而失去了灵活性,所以我决定重写一个自己的布局管理器来实现。经过分析,所有的LayoutManager都要实现一个接口,就是LayoutManager交互或者是他的一个子接口LayoutManager2接口,后者用于复杂的布局管理,例如GridCardLayout.LayoutManager有五个方法需要实现,分别是:
1、公共空addLayoutComponent(字符串名称、组件comp);
2、公共空removeLayoutComponent comp(组件);
3、公共维度preferredLayoutSize(容器容器);
4、公共维度minimumLayoutSize(容器容器);
5、公共空layoutContainer(容器容器);
第一个方法其实就是你在使用容器。添加(comp字符串名称、组件);时调用的方法,例如BorderLayout为布局管理器时。但在FlowLayout中由于没有其他的附加信息,所以不需要填充这个方法。相应的第二个方法也就不需要填充了。真正核心的方法是第三个和第五个方法,前者是最终确定容器有多大的,而后者就是决定容器中各个小件的实际位置的了。也就是说,当我们用container.setLayout (LayoutManager)后,再加入小件后,最后系统做的工作其实是LayoutManager。layoutContainer(容器);和container.setSize (LayoutManager。PreferredLayoutSize(容器));。
下面是我的新类:VflowLayout。
包render_account;
进口java.awt。*;
进口. io . *;
公共类VFlowLayout实现LayoutManager Serializable {
int hgap;
int vgap;
公共VFlowLayout () {
(5);
}
公共VFlowLayout (int, int j) {
this.hgap=我;
this.vgap=j;
}
公共空间addLayoutComponent (comp字符串名称、组件){
}
公共空间removeLayoutComponent comp(组件){
}
公共维度preferredLayoutSize(容器容器){
同步(container.getTreeLock ()) {
维dimension1=新维度(0,0);
int i=container.getComponentCount ();
for (int j=0; j=container.getComponent组件组件(j);
如果(component.isVisible ()) {
维dimension2=component.getPreferredSize ();
dimension1.width=Math.max (dimension1.width dimension2.width);
如果(j> 0)
dimension1.height +=vgap;
dimension1.height +=dimension2.height;
}
}
Insets Insets=container.getInsets ();
dimension1.height +=insets.top + insets.bottom + vgap * 2;
dimension1.width +=insets.left + insets.right + hgap * 2;
维维=dimension1;
返回维度;
文件://返回(新维度(50200));
}
}
公共维度minimumLayoutSize(容器容器){
同步(container.getTreeLock ()) {
维dimension1=新维度(0,0);
int i=container.getComponentCount ();
for (int j=0; j=container.getComponent组件组件(j);
如果(component.isVisible ()) {
维dimension2=component.getMinimumSize ();
dimension1.width=Math.max (dimension1.width dimension2.width);
如果(j> 0)
dimension1.height +=vgap;
dimension1.height +=dimension2.height;
}
}
Insets Insets=container.getInsets ();
dimension1.height +=insets.top + insets.bottom + vgap * 2;
dimension1.width +=insets.left + insets.right + hgap * 2;
维维=dimension1;
返回维度;
}
}
公共空间layoutContainer(容器容器){
同步(container.getTreeLock ()) {
Insets Insets=container.getInsets ();
int vSpace=container.getSize () .height (insets.top + insets.bottom + vgap * 2);
int componentCount=container.getComponentCount ();
int左=insets.left + hgap;
int totalHeight=0;
int宽度=0;
int componentStart=0;
(int i=0;我组件组件=container.getComponent(我);
如果(component.isVisible ()) {
维维=component.getPreferredSize ();
component.setSize (dimension.width dimension.height);
如果(totalHeight==0 | | totalHeight + dimension.height0)
totalHeight +=vgap;
totalHeight +=dimension.height;
宽度=Math.max(宽度、dimension.width);
其他}{
moveComponents(容器,insets.top + vgap,左,宽度,componentStart, i);
totalHeight=0;
左+=hgap +宽度;
宽度=dimension.width;
componentStart=我;
}
}
}
moveComponents(容器,insets.top + vgap,左,宽度,componentStart, componentCount);
}
}
私人空间moveComponents(容器容器,int, int, int宽度,int componentStart, int componentEnd) {
同步(container.getTreeLock ()) {
for (int i=componentStart;我组件组件=container.getComponent(我);
如果(component.isVisible ()) {
component.setLocation(左前);
前+=component.getPreferredSize () .height + vgap;
}
}
}
}
公共空间setHgap (int i) {
this.hgap=我;
}
公共空间setVgap (int i) {
this.vgap=我;
}
公共int getHgap () {
返回(this.hgap);
}
公共int getVgap () {
返回(this.vgap);
}
}
大家可以试一下。[@more@]