Here's what I found useful for laying out components in some circumstances easier and more precise than Java's GridBagLayout. --CostinCozianu. For the design of the client API, I applied EmulateKeywordAndDefaultParameters. A layout that describes a grid, pretty much like GridBagLayout, the width of a column is given as a float. If it is greater than 1 than it is converted as int and sets the fixed number of pixels for that column, if it is within (0,1) it represents the weight in the distribution of free space. So is with the rows. Therefore a construction: float lineParams[] = new float[] { 50f, .7f, .2f, 50f }; float columnParams[] = new float [] { .1f, .5f,.1f,75f}; new GridLayoutEx(lineParams,columnParams,2,2); Represents a grid with first and fourth line fixed as 50 pixels, the second and third line divide their space proportionally to 7 and 2 (the sum of the "quota" (0,1) parameters need not be 1).The last column has a fixed size of 75 pixels while the first three columns divide the space proportionally with 1,5,1. There's a gap space between rows and columns of 2 pixels. package home.costin.ui; import java.awt.*; import java.io.ObjectStreamException; import java.io.Serializable; /** * Insert the type's description here. * Creation date: (9/18/2001 10:44:40 AM) * * License: APACHE LICENSE * http://www.apache.org/LICENSE.txt * @author: Costin Cozianu */ public class GridLayoutEx implements LayoutManager2 { /** * Enumeration constants to use for Fill values */ public static final FillOption NO_FILL= new FillOption(0), FILL= new FillOption(1); private final static FillOption[] FILL_CONSTS ={NO_FILL,FILL}; /** * TypeSafe Enumeration for FillOptions * @author ccozianu */ public static class FillOption implements Serializable { private int i=0; private FillOption(int i_) {this.i=i_;} private Object readResolve() throws ObjectStreamException { return FILL_CONSTS[i]; } public boolean equals(Object o) { if (this==o) return true; else return this.i== ((FillOption)o).i; } public int hashCode(){ return i; } } /** * Constants for vertical alignment */ public static final VAlignOption VA_CENTER= new VAlignOption(0), VA_BOTTOM= new VAlignOption(1), VA_TOP= new VAlignOption(2); private final static VAlignOption[] VALIGN_CONSTS ={VA_CENTER,VA_BOTTOM,VA_TOP}; /** * Type-safe enumeration for vertical alignment * @author ccozianu */ public static class VAlignOption implements Serializable { private int i=0; private VAlignOption(int i_) {this.i=i_;} private Object readResolve() throws ObjectStreamException { return VALIGN_CONSTS[i]; } public boolean equals(Object o) { if (this==o) return true; else return this.i== ((VAlignOption)o).i; } public int hashCode(){ return i; } } /** * Constants for vertical alignment */ public static final HAlignOption HA_CENTER= new HAlignOption(0), HA_LEFT= new HAlignOption(1), HA_RIGHT= new HAlignOption(2); private final static HAlignOption[] HALIGN_CONSTS ={HA_CENTER,HA_LEFT,HA_RIGHT}; /** * Type-safe enumeration for vertical alignment * @author ccozianu */ public static class HAlignOption implements Serializable { private int i=0; private HAlignOption(int i_) {this.i=i_;} private Object readResolve() throws ObjectStreamException { return HALIGN_CONSTS[i]; } public boolean equals(Object o) { if (this==o) return true; else return this.i== ((HAlignOption)o).i; } public int hashCode(){ return i; } } public static class Constraint implements Serializable, Cloneable { private int line=0, column=0, rowspan=1, colspan=1; public Constraint setLine(int line_) { this.line= line_; return this; } public Constraint setColumn(int column_ ) { this.column= column_; return this; } public Constraint setRowspan(int rowspan_) {this.rowspan= rowspan_; return this;} public Constraint setColspan(int colspan_ ) { this.colspan= colspan_; return this; } public Insets insets= new Insets(0,0,0,0); public Constraint setInsets(Insets insets_) {this.insets= insets_; return this; } private FillOption verticalFill= NO_FILL; private FillOption horizontalFill= NO_FILL; public Constraint setVerticalFill(FillOption option){ this.verticalFill=option; return this;}; public Constraint setHorizontalFill(FillOption option){ this.horizontalFill=option; return this;}; private VAlignOption verticalAlign= VA_CENTER; private HAlignOption horizontalAlign= HA_CENTER; public Constraint setVerticalAlign(VAlignOption option) {this.verticalAlign= option; return this; } public Constraint setHAlignOption(HAlignOption option) {this.horizontalAlign= option; return this;} public Object clone() throws CloneNotSupportedException { /*Constraint result= new Constraint(); result.colspan= colspan; result.rowspan= rowspan; result.column= column; result.line= line; result.insets= (Insets) (insets==null? null : insets.clone());*/ return (Constraint) super.clone(); } private void computeBoundsInsideTheCell( Component comp, int x, int y, int w, int h){ x += insets.left; y += insets.top; w -= insets.right; h -= insets.bottom; Dimension d= comp.getPreferredSize(); if (horizontalFill==NO_FILL){ if (d.getWidth()< w){ if (horizontalAlign==HA_LEFT){ w= (int)d.getWidth(); } else if (horizontalAlign==HA_RIGHT){ x += ( w - d.getWidth()); w = (int)d.getWidth(); } else if (horizontalAlign==HA_CENTER) { x += (w-d.getWidth())/2; w= (int) d.getWidth(); } }} if (verticalFill==NO_FILL){ if (d.getHeight()< h){ if (verticalAlign==VA_TOP){ h= (int)d.getHeight(); } else if (verticalAlign==VA_BOTTOM){ y += ( h - d.getHeight()); h = (int)d.getHeight(); } else if (verticalAlign==VA_CENTER) { y += (h-d.getHeight())/2; h= (int) d.getHeight(); } }} comp.setBounds(x, y, w, h); } } java.util.Hashtable components= new java.util.Hashtable(); /** * specifies whether or not the row parameters are specified by quota * if rowParamIsQuota[i]==true then the parameter is a quota * that specifies how much of the available space should be given to the i-th row * and should be read from rowParamsQuota
* else the parameter is the fixed height of the row and should be taken from * rowParamsInt */ private boolean[] rowParamIsQuota; private float[] rowParamsQuota; private int[] rowParamsInt; private int rowCount; private boolean[] columnParamIsQuota; private int[] columnParamsInt; private float[] columnParamsQuotas; private int colCount; private int reservedWidth; private int hgap; private int vgap; private int reservedHeight; /** * buffer used to calculate rowCoordinates in layout procedure */ private transient int rowCoordinates[] = null; /** * buffer used to calculate rowCoordinates in layout procedure */ private transient int columnCoordinates[] = null; public G''''''ridLayoutEx (float [] lineParams, float [] columnParams) { this(lineParams,columnParams,1,1); } public G''''''ridLayoutEx (float [] rowParams, float [] columnParams, int hgap, int vgap) { if (rowParams == null || rowParams.length == 0) throw new I''''''llegalArgumentException("Illegal lineParams "); if (columnParams == null || columnParams.length == 0) throw new I''''''llegalArgumentException("Illegal columnParams "); rowCount= rowParams.length; colCount= columnParams.length; this.hgap= hgap<0 ? 0 : hgap; this.vgap= vgap<0 ? 0 : vgap; rowParamIsQuota= new boolean[rowCount]; rowParamsQuota= new float[rowCount]; rowParamsInt= new int[rowCount]; columnParamIsQuota= new boolean [colCount]; columnParamsQuotas= new float [colCount]; columnParamsInt= new int[colCount]; float sumOfLines=0; for (int i=0; iminimum size such * that all components get a size greater than or equal to their preferred size * and the rows or columns that are fixed size remain fixed * @see #minimumLayoutSize */ public Dimension preferredLayoutSize(Container parent) { Insets insets= parent.getInsets(); Component [] compArray= parent.getComponents(); int [] preferredRowSizes= new int[rowCount]; int [] preferredColSizes= new int[colCount]; for (int x=0;x preferredRowSizes[r]) preferredRowSizes[r]= rowSize; } } int beginCol= constraint.column; int endCol= beginCol+ constraint.colspan; float totalColWeight=0f; for (int col=beginCol;col preferredColSizes[col]) preferredColSizes[col]= colSize; } } } //done cycling through components // let cycle through rows and columns to get the dimensions int adjustableHeight=0; for (int row=0;row < rowCount; row++) { if (rowParamIsQuota[row]) { int requiredHeight= ( int) (preferredRowSizes[row] / rowParamsQuota[row]); if (requiredHeight>adjustableHeight) adjustableHeight= requiredHeight; } } int adjustableWidth=0; for (int col=0;col < colCount; col++) { if (columnParamIsQuota[col]) { int requiredWidth= ( int) (preferredColSizes[col] / columnParamsQuotas[col]); if (requiredWidth>adjustableWidth) adjustableWidth= requiredWidth; } } return new Dimension(reservedWidth+ adjustableWidth + colCount * hgap , reservedHeight + adjustableHeight + rowCount * vgap); } /** * Removes the specified component from the layout. * @param comp the component to be removed */ public void removeLayoutComponent(Component comp) { components.remove(comp); } }