我们都知道,java的gui界面定义是由awt类和swing类来完成的。它在布局管理上面采用了容器和布局管理分离的方案。也就是说,容器只管将其他小件放入其中,而不管这些小件是如何放置的。对于布局的管理交给专门的布局管理器类(layoutmanager)来完成。
其实,java在gui方面应该是并不成功的。awt类和swing类的结构非常复杂,加上充斥其间的子类继承和接口实现,使得要想掌握这两个类非常困难。这也是很多的java程序员抱怨的事情,但gui已经成了程序发展的方向,所以这里我们也得勉为其难了。
现在我们来看java中布局管理器的具体实现。我们前面说过,java中的容器类(container),它们只管加入小件(meta),也就是说,它只使用自己的add()方法向自己内部加入小件。同时他记录这些加入其内部的小件的个数,可以通过container.getcomponentcount()方法类获得小件的数目,通过container.getcomponent(i)来获得相应小件的句柄。然后layoutmanager类就可以通过这些信息来实际布局其中的小件了。
java已经为我们提供了几个常用的布局管理器类,例如:borderlayout、flowlayout、gridbaglayout等等。但在实际的布局上,我们还是会有其他的需要。我在不久前的一个问题中曾经要一个垂直的流式布局,我称之为vflowlayout,其实boxlayout和gridbaglayout可以完成类似的工作,但前者是swing类的成员,我的客户端是一个applet,不能使用,而后者必须在类生成的时候指定列数,而失去了灵活性,所以我决定重写一个自己的布局管理器来实现。经过分析,所有的layoutmanager都要实现一个接口,就是layoutmanager inerface或者是他的一个子接口layoutmanager2 interface,后者用于复杂的布局管理,例如gridcardlayout。layoutmanager有五个方法需要实现,分别是:
1、public void addlayoutcomponent(string name, component comp);
2、public void removelayoutcomponent(component comp);
3、public dimension preferredlayoutsize(container container);
4、public dimension minimumlayoutsize(container container);
5、public void layoutcontainer(container container);
第一个方法其实就是你在使用container.add(string name,component comp);时调用的方法,例如borderlayout为布局管理器时。但在flowlayout中由于没有其他的附加信息,所以不需要填充这个方法。相应的第二个方法也就不需要填充了。真正核心的方法是第三个和第五个方法,前者是最终确定container有多大的,而后者就是决定container中各个小件的实际位置的了。也就是说,当我们用container.setlayout(layoutmanager)后,再加入小件后,最后系统做的工作其实是layoutmanager. layoutcontainer(container);和container.setsize(layoutmanager. preferredlayoutsize(container));。
下面是我的新类:vflowlayout。
package render_account;
import java.awt.*;
import java.io.*;
public class vflowlayout implements layoutmanager,serializable{
int hgap;
int vgap;
public vflowlayout(){
this(5,5);
}
public vflowlayout(int i,int j){
this.hgap=i;
this.vgap=j;
}
public void addlayoutcomponent(string name, component comp){
}
public void removelayoutcomponent(component comp){
}
public dimension preferredlayoutsize(container container){
synchronized(container.gettreelock()){
dimension dimension1=new dimension(0,0);
int i=container.getcomponentcount();
for(int j=0;j component component = container.getcomponent(j);
if(component.isvisible()){
dimension dimension2=component.getpreferredsize();
dimension1.width=math.max(dimension1.width,dimension2.width);
if(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;
dimension dimension=dimension1;
return dimension;
file://return(new dimension(50,200));
}
}
public dimension minimumlayoutsize(container container){
synchronized(container.gettreelock()){
dimension dimension1=new dimension(0,0);
int i=container.getcomponentcount();
for(int j=0;j component component = container.getcomponent(j);
if(component.isvisible()){
dimension dimension2=component.getminimumsize();
dimension1.width=math.max(dimension1.width,dimension2.width);
if(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;
dimension dimension=dimension1;
return dimension;
}
}
public void layoutcontainer(container container){
synchronized(container.gettreelock()){
insets insets=container.getinsets();
int vspace=container.getsize().height-(insets.top+insets.bottom+vgap*2);
int componentcount=container.getcomponentcount();
int left=insets.left+hgap;
int totalheight=0;
int width=0;
int componentstart=0;
for(int i=0;i component component=container.getcomponent(i);
if(component.isvisible()){
dimension dimension=component.getpreferredsize();
component.setsize(dimension.width,dimension.height);
if(totalheight==0 || totalheight+dimension.height<=vspace){
if(totalheight>0)
totalheight+=vgap;
totalheight+=dimension.height;
width=math.max(width,dimension.width);
}else{
movecomponents(container,insets.top+vgap,left,width,componentstart,i);
totalheight=0;
left+=hgap+width;
width=dimension.width; componentstart=i;
}
}
}
movecomponents(container,insets.top+vgap,left,width,componentstart,componentcount);
}
}
private void movecomponents(container container,int top,int left,int width,int componentstart,int componentend){
synchronized(container.gettreelock()){
for(int i=componentstart;i component component=container.getcomponent(i);
if(component.isvisible()){ component.setlocation(left,top); top+=component.getpreferredsize().height+vgap;
}
}
}
}
public void sethgap(int i){
this.hgap=i;
}
public void setvgap(int i){
this.vgap=i;
}
public int gethgap(){
return(this.hgap);
}
public int getvgap(){
return(this.vgap);
}
}
大家可以试一下。
闽公网安备 35060202000074号