CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    How to prevent GridLayout from vertically stretching?

    Hi,

    I've been using GridLayout in a JTabbedPane. I ran into a problem when I created my 2nd pane. The 2nd is smaller (in height) than the 1st, so it gets streched to the same size as the 1st. I'm using GridLayout to line up controls left edges. But on the 2nd tab page it stretches the height of the combo boxes. Is there a way to prevent this somehow? I'm aware of more advanced layout managers that I will eventually look into, but for now I was wondering if theres any trick I could use to prevent GridLayout from vertically stretching. I've had limited success with putting the combo box inside a sub pane set to FlowLayout, but I was wondering if there was an easier/better way.

    Thanks

  2. #2
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    Re: How to prevent GridLayout from vertically stretching?

    Nevermind

    I solved it by calling setMaximumSize() on the JPanel that is the 2nd tabbed dialog pane. I initially tried setPreferredSize(), and when that didnt work, I thought setMaximumSize also wouldnt work but I was wrong.

  3. #3
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    Re: How to prevent GridLayout from vertically stretching?

    Nevermind on the nevermind

    Using setMaximumSize solved the problem of the 2nd pane stretching to the same height as the 1st, but I still have problems with the combobox being height stretched.

  4. #4
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: How to prevent GridLayout from vertically stretching?

    What happens if you set maximum size on the combobox?

    Learning is never done without errors and defeat...
    V. Lenin
    Please use [CODE]...your code here...[/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  5. #5
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    Re: How to prevent GridLayout from vertically stretching?

    Hi Dlorde,
    I tried that..it sounded promising..but it didnt work. Right now I'm going over the java tutorials on layout managers in more detail. Thanks for the help.

  6. #6
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    Re: How to prevent GridLayout from vertically stretching?

    You could try the following layout manager. It's a variation of GridLayout but instead of setting all rectangles to the same size it sets the width of each column and the height of each row to the largest preferred size in each column/row. So basically you get a grid of components but the columns widths and row heights vary to suit the preferred sizes of the components in them. It's a direct plug in for GridLayout so the only line you need to change is where you set the layout. You'll have to change it to something like: myPanel.setLayout(new VariableGridLayout());

    Be warned though, I've just knocked this up tonight by editing the original GridLayout code so it's not fully tested. If you come across any bugs let me know.


    Code:
    import java.awt.*;
    
    /**
     * The <code>VariableGridLayout</code> class is a layout manager that
     * lays out a container's components in a rectangular grid.
     * The container is divided into rectangles where the width of a
     * column is ratio of the preferred width of the widest component in
     * that column and the hieght of a row is a ratio of the preferred
     * height of the highest component in that row.
     * One component is placed in each rectangle.
     * <p>
     * When both the number of rows and the number of columns have
     * been set to non-zero values, either by a constructor or
     * by the <tt>setRows</tt> and <tt>setColumns</tt> methods, the number of
     * columns specified is ignored.  Instead, the number of
     * columns is determined from the specified number of rows
     * and the total number of components in the layout. So, for
     * example, if three rows and two columns have been specified
     * and nine components are added to the layout, they will
     * be displayed as three rows of three columns.  Specifying
     * the number of columns affects the layout only when the
     * number of rows is set to zero.
     *
     * This class is based on the original GridLayout code by Arthur van Hoff
     * version 1.42, 11/17/05
     *
     *
     * @author  A G Docherty
     * @version 1.1, 29/02/2007
     */
    public class VariableGridLayout implements LayoutManager, java.io.Serializable {
        /*
         * serialVersionUID
         */
        private static final long serialVersionUID = -7804673224730901L;
    
        /**
         * This is the horizontal gap (in pixels) which specifies the space
         * between columns.  They can be changed at any time.
         * This should be a non-negative integer.
         *
         * @serial
         * @see #getHgap()
         * @see #setHgap(int)
         */
        int hgap;
        /**
         * This is the vertical gap (in pixels) which specifies the space
         * between rows.  They can be changed at any time.
         * This should be a non negative integer.
         *
         * @serial
         * @see #getVgap()
         * @see #setVgap(int)
         */
        int vgap;
        /**
         * This is the number of rows specified for the grid.  The number
         * of rows can be changed at any time.
         * This should be a non negative integer, where '0' means
         * 'any number' meaning that the number of Rows in that
         * dimension depends on the other dimension.
         *
         * @serial
         * @see #getRows()
         * @see #setRows(int)
         */
        int rows;
        /**
         * This is the number of columns specified for the grid.  The number
         * of columns can be changed at any time.
         * This should be a non negative integer, where '0' means
         * 'any number' meaning that the number of Columns in that
         * dimension depends on the other dimension.
         *
         * @serial
         * @see #getColumns()
         * @see #setColumns(int)
         */
        int cols;
    
        /**
         * Creates a grid layout with a default of one column per component,
         * in a single row.
         * @since JDK1.1
         */
        public VariableGridLayout() {
    	this(1, 0, 0, 0);
        }
    
        /**
         * Creates a grid layout with the specified number of rows and
         * columns.
         * <p>
         * One, but not both, of <code>rows</code> and <code>cols</code> can
         * be zero, which means that any number of objects can be placed in a
         * row or in a column.
         * @param     rows   the rows, with the value zero meaning
         *                   any number of rows.
         * @param     cols   the columns, with the value zero meaning
         *                   any number of columns.
         */
        public VariableGridLayout(int rows, int cols) {
    	this(rows, cols, 0, 0);
        }
    
        /**
         * Creates a grid layout with the specified number of rows and
         * columns.
         * <p>
         * In addition, the horizontal and vertical gaps are set to the
         * specified values. Horizontal gaps are placed between each
         * of the columns. Vertical gaps are placed between each of
         * the rows.
         * <p>
         * One, but not both, of <code>rows</code> and <code>cols</code> can
         * be zero, which means that any number of objects can be placed in a
         * row or in a column.
         * <p>
         * All <code>VariableGridLayout</code> constructors defer to this one.
         * @param     rows   the rows, with the value zero meaning
         *                   any number of rows
         * @param     cols   the columns, with the value zero meaning
         *                   any number of columns
         * @param     hgap   the horizontal gap
         * @param     vgap   the vertical gap
         * @exception   IllegalArgumentException  if the value of both
         *			<code>rows</code> and <code>cols</code> is
         *			set to zero
         */
        public VariableGridLayout(int rows, int cols, int hgap, int vgap) {
    	if ((rows == 0) && (cols == 0)) {
    	    throw new IllegalArgumentException("rows and cols cannot both be zero");
    	}
    	this.rows = rows;
    	this.cols = cols;
    	this.hgap = hgap;
    	this.vgap = vgap;
        }
    
        /**
         * Gets the number of rows in this layout.
         * @return    the number of rows in this layout
         * @since     JDK1.1
         */
        public int getRows() {
    	return rows;
        }
    
        /**
         * Sets the number of rows in this layout to the specified value.
         * @param        rows   the number of rows in this layout
         * @exception    IllegalArgumentException  if the value of both
         *               <code>rows</code> and <code>cols</code> is set to zero
         * @since        JDK1.1
         */
        public void setRows(int rows) {
    	if ((rows == 0) && (this.cols == 0)) {
    	    throw new IllegalArgumentException("rows and cols cannot both be zero");
    	}
    	this.rows = rows;
        }
    
        /**
         * Gets the number of columns in this layout.
         * @return     the number of columns in this layout
         * @since      JDK1.1
         */
        public int getColumns() {
    	return cols;
        }
    
        /**
         * Sets the number of columns in this layout to the specified value.
         * Setting the number of columns has no affect on the layout
         * if the number of rows specified by a constructor or by
         * the <tt>setRows</tt> method is non-zero. In that case, the number
         * of columns displayed in the layout is determined by the total
         * number of components and the number of rows specified.
         * @param        cols   the number of columns in this layout
         * @exception    IllegalArgumentException  if the value of both
         *               <code>rows</code> and <code>cols</code> is set to zero
         * @since        JDK1.1
         */
        public void setColumns(int cols) {
    	if ((cols == 0) && (this.rows == 0)) {
    	    throw new IllegalArgumentException("rows and cols cannot both be zero");
    	}
    	this.cols = cols;
        }
    
        /**
         * Gets the horizontal gap between components.
         * @return       the horizontal gap between components
         * @since        JDK1.1
         */
        public int getHgap() {
    	return hgap;
        }
    
        /**
         * Sets the horizontal gap between components to the specified value.
         * @param        hgap   the horizontal gap between components
         * @since        JDK1.1
         */
        public void setHgap(int hgap) {
    	this.hgap = hgap;
        }
    
        /**
         * Gets the vertical gap between components.
         * @return       the vertical gap between components
         * @since        JDK1.1
         */
        public int getVgap() {
    	return vgap;
        }
    
        /**
         * Sets the vertical gap between components to the specified value.
         * @param         vgap  the vertical gap between components
         * @since        JDK1.1
         */
        public void setVgap(int vgap) {
    	this.vgap = vgap;
        }
    
        /**
         * Adds the specified component with the specified name to the layout.
         * @param name the name of the component
         * @param comp the component to be added
         */
        public void addLayoutComponent(String name, Component comp) {
        }
    
        /**
         * Removes the specified component from the layout.
         * @param comp the component to be removed
         */
        public void removeLayoutComponent(Component comp) {
        }
    
        /**
         * Determines the preferred size of the container argument using
         * this grid layout.
         * <p>
         * The preferred width of a grid layout is the sum of the components
         * largest preferred width of each column
         * plus the horizontal padding times the number of columns
         * minus one, plus the left and right insets of the target container.
         * <p>
         * The preferred height of a grid layout is the sum of the components
         * largest preferred height of each row times the number of
         * rows, plus the vertical padding times the number of rows minus one,
         * plus the top and bottom insets of the target container.
         *
         * @param     parent   the container in which to do the layout
         * @return    the preferred dimensions to lay out the
         *                      subcomponents of the specified container
         * @see       java.awt.VariableGridLayout#minimumLayoutSize
         * @see       java.awt.Container#getPreferredSize()
         */
        public Dimension preferredLayoutSize(Container parent) {
          synchronized (parent.getTreeLock()) {
    	Insets insets = parent.getInsets();
    	int ncomponents = parent.getComponentCount();
    	int nrows = rows;
    	int ncols = cols;
    
    	if (nrows > 0) {
    	    ncols = (ncomponents + nrows - 1) / nrows;
    	} else {
    	    nrows = (ncomponents + ncols - 1) / ncols;
    	}
    
        int[] colWidths = new int[ncols];
        int[] rowHeights = new int[nrows];
        Component[] comps = parent.getComponents();
    
    	for (int i = 0 ; i < nrows ; i++) {
            for ( int j = 0; j < ncols; ++j ) {
                int idx = i * ncols + j;
    
                if ( idx >= comps.length ) {
                    break;
                    }
    
                Component comp = comps[idx];
        	    Dimension d = comp.getPreferredSize();
    
        	    if (colWidths[j] < d.width) {
            		colWidths[j] = d.width;
                }
    
        	    if (rowHeights[i] < d.height) {
        		    rowHeights[i] = d.height;
                }
            }
    	}
    
        int w = 0;
    	for (int i = 0 ; i < ncols ; i++) {
            w += colWidths[i];
        }
    
        int h = 0;
    	for (int i = 0 ; i < nrows ; i++) {
            h += rowHeights[i];
        }
    
    	return new Dimension(insets.left + insets.right + w + (ncols-1)*hgap,
    			     insets.top + insets.bottom + h + (nrows-1)*vgap);
          }
        }
    
        /**
         * Determines the minimum size of the container argument using this
         * grid layout.
         * <p>
         * The minimum width of a grid layout is the sum of the components
         * largest minimum width of each column
         * plus the horizontal padding times the number of columns
         * minus one, plus the left and right insets of the target container.
         * <p>
         * The minimum height of a grid layout is the sum of the components
         * largest minimum height of each row times the number of
         * rows, plus the vertical padding times the number of rows minus one,
         * plus the top and bottom insets of the target container.
         *
         * @param       parent   the container in which to do the layout
         * @return      the minimum dimensions needed to lay out the
         *                      subcomponents of the specified container
         * @see         java.awt.VariableGridLayout#preferredLayoutSize
         * @see         java.awt.Container#doLayout
         */
        public Dimension minimumLayoutSize(Container parent) {
          synchronized (parent.getTreeLock()) {
    	Insets insets = parent.getInsets();
    	int ncomponents = parent.getComponentCount();
    	int nrows = rows;
    	int ncols = cols;
    
    	if (nrows > 0) {
    	    ncols = (ncomponents + nrows - 1) / nrows;
    	} else {
    	    nrows = (ncomponents + ncols - 1) / ncols;
    	}
    
        int[] colWidths = new int[ncols];
        int[] rowHeights = new int[nrows];
        Component[] comps = parent.getComponents();
    
    	for (int i = 0 ; i < nrows ; i++) {
            for ( int j = 0; j < ncols; ++j ) {
                int idx = i * ncols + j;
    
                if ( idx >= comps.length ) {
                    break;
                    }
    
                Component comp = comps[idx];
        	    Dimension d = comp.getMinimumSize();
    
        	    if (colWidths[j] < d.width) {
            		colWidths[j] = d.width;
                }
    
        	    if (rowHeights[i] < d.height) {
        		    rowHeights[i] = d.height;
                }
            }
    	}
    
        int w = 0;
    	for (int i = 0 ; i < ncols ; i++) {
            w += colWidths[i];
        }
    
        int h = 0;
    	for (int i = 0 ; i < nrows ; i++) {
            h += rowHeights[i];
        }
    
    	return new Dimension(insets.left + insets.right + w + (ncols-1)*hgap,
    			     insets.top + insets.bottom + h + (nrows-1)*vgap);
          }
        }
    
        /**
         * Lays out the specified container using this layout.
         * <p>
         * This method reshapes the components in the specified target
         * container in order to satisfy the constraints of the
         * <code>VariableGridLayout</code> object.
         * <p>
         * The varaible grid layout manager determines the size of individual
         * components by dividing the free space in the container into
         * unequal portions according to relative maximum preferred sizes of
         * largest component in each row and column in the layout.
         * The container's free space equals the container's
         * size minus any insets and any specified horizontal or vertical
         * gap.
         *
         * @param      parent   the container in which to do the layout
         * @see        java.awt.Container
         * @see        java.awt.Container#doLayout
         */
        public void layoutContainer(Container parent) {
          synchronized (parent.getTreeLock()) {
    	Insets insets = parent.getInsets();
    	int ncomponents = parent.getComponentCount();
    	int nrows = rows;
    	int ncols = cols;
    	boolean ltr = parent.getComponentOrientation().isLeftToRight();
    
    	if (ncomponents == 0) {
    	    return;
    	}
    	if (nrows > 0) {
    	    ncols = (ncomponents + nrows - 1) / nrows;
    	} else {
    	    nrows = (ncomponents + ncols - 1) / ncols;
    	}
    	int w = parent.getWidth() - (insets.left + insets.right)  - (ncols - 1) * hgap;
    	int h = parent.getHeight() - (insets.top + insets.bottom) - (nrows - 1) * vgap;
    
        int[] colWidths = new int[ncols];
        int[] rowHeights = new int[nrows];
        Component[] comps = parent.getComponents();
    
    	for (int i = 0 ; i < nrows ; i++) {
            for ( int j = 0; j < ncols; ++j ) {
                int idx = i * ncols + j;
    
                if ( idx >= comps.length ) {
                    break;
                    }
    
                Component comp = comps[idx];
        	    Dimension d = comp.getPreferredSize();
    
        	    if (colWidths[j] < d.width) {
            		colWidths[j] = d.width;
                }
    
        	    if (rowHeights[i] < d.height) {
        		    rowHeights[i] = d.height;
                }
            }
    	}
    
        int prefW = 0;
    	for (int i = 0 ; i < ncols ; i++) {
            prefW += colWidths[i];
        }
    
        int prefH = 0;
    	for (int i = 0 ; i < nrows ; i++) {
            prefH += rowHeights[i];
        }
    
        double ratioW = (double)w/prefW;
        double ratioH = (double)h/prefH;
    
    	if (ltr) {
    	    for (int c = 0, x = insets.left ; c < ncols ; c++, x += w + hgap) {
    		for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) {
    		    int i = r * ncols + c;
    		    if (i < ncomponents) {
        			Component comp = parent.getComponent(i);
    
                    w = (int)(colWidths[c] * ratioW);
                    h = (int)(rowHeights[r] * ratioH);
    
        			comp.setBounds(x, y, w, h);
    		    }
    		}
    	    }
    	} else {
    	    for (int c = 0, x = parent.getWidth() - insets.right - w; c < ncols ; c++, x -= w + hgap) {
    		for (int r = 0, y = insets.top ; r < nrows ; r++, y += h + vgap) {
    		    int i = r * ncols + c;
    		    if (i < ncomponents) {
        			Component comp = parent.getComponent(i);
    
                    w = (int)(colWidths[c] * ratioW);
                    h = (int)(rowHeights[r] * ratioH);
    
        			comp.setBounds(x, y, w, h);
    		    }
    		}
    	    }
    	}
          }
        }
    
        /**
         * Returns the string representation of this grid layout's values.
         * @return     a string representation of this grid layout
         */
        public String toString() {
    	return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap +
    	    			       ",rows=" + rows + ",cols=" + cols + "]";
        }
    }
    Last edited by keang; March 1st, 2007 at 11:35 AM. Reason: Bug Fix - Layout didn't take account of hgap and vgap settings

  7. #7
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    Re: How to prevent GridLayout from vertically stretching?

    Thanks for that code keang

    Although, I did 'bite the bullet' and read the java layout tutorials again. In summary:

    1. I got scared away from GridBagLayout because, according to the sun tutorial:

    GridBagLayout is one of the most flexible — and complex — layout managers the Java platform provides
    The 'and complex' part scared me away...but it wasnt really that complex. I'd say that GroupLayout is more complicated, IMHO

    2. What kept stumping me was that setPreferredSize & setMax/MinSize seemed to be unreliable. I finally learned that different layout managers 'respect' components min, max & preferred wishes, while others dont. That was a big 'aha' moment.

    Thanks again Keang. I'll keep this code in mind for the future.

    -Martin

  8. #8
    Join Date
    May 2006
    Location
    UK
    Posts
    4,473

    Re: How to prevent GridLayout from vertically stretching?

    Code:
    The 'and complex' part scared me away...but it wasnt really that complex.
    The biggest problem I've found with GridBagLayout is not with initially writing the code - once you decided how you want the layout it is a fairly logical but long winded process - it's when you want to add/change some controls at some time in the future. If you've got a complex layout, trying to work out how all those constraints interact with each other can be an onerous task.

    I'd say that GroupLayout is more complicated, IMHO
    GroupLayout is actually intended for GUI builders but can be hand coded. I guess it may seem complex at first because it's designed to be easy for GUI builders to the write code rather than humans.

    2. What kept stumping me was that setPreferredSize & setMax/MinSize seemed to be unreliable. I finally learned that different layout managers 'respect' components min, max & preferred wishes, while others dont. That was a big 'aha' moment.
    I had the same moment when I was first using LayoutManagers. Some of the documentation could be clearer on which sizes are/aren't honoured/considered/ignored etc.

    Thanks again Keang. I'll keep this code in mind for the future.
    No problem it only took 1/2 hour (all I did was modify existing code to change the functionality a little) and was an interesting excercise as well.

  9. #9
    Join Date
    Apr 2021
    Posts
    1

    Re: How to prevent GridLayout from vertically stretching?

    Have you tried adding extra "empty" rows to the GridLayout manager?

    Extra rows will be of same height as others so can help squeeze things manually. Just an alternative.

  10. #10
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: How to prevent GridLayout from vertically stretching?

    Dear isho777!
    This thread is 14 years old! Are you sure the OP till needs your opinion?
    Victor Nijegorodov

  11. #11
    Join Date
    Jun 2021
    Posts
    10

    Re: How to prevent GridLayout from vertically stretching?

    Please use layout_column and layout_row to specify in which row and in which column of that row you want to place your ImageView.

    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:columnCount="4"
        android:rowCount="4"
        tools:context=".MainActivity" >
    
     <ImageView
       android:layout_column="1"
       android:layout_row="0"
       android:src="@drawable/pic1" />
    
     <ImageView
       android:layout_column="2"
       android:layout_row="0"
       android:src="@drawable/pic2" />
    
    </GridLayout>

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured