#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2009
    Posts
    1
    Rep Power
    0

    Vertical FlowLayout??


    Hi I am trying to create a JPanel that has dynamically added JCheckBox's. The original design used FlowLayout manager (the default). This was OK to start with as there was only a handful of JCheckBox required, resizing the JFrame and likewise the JPanel enabled more columns of JCheckBox's across the screen. The problem now is the requirements have changed and I now need to have a lot more JCheckBox's, of which some cannot be seen off the bottom of the JPanel. I tried adding a JScrollPane but this has meant the JCheckBox's are all in one row with only a horizontal scroll bar, what I really want is to have the columns of JCheckBox's which can be resized (1,2,3,n columns wide depending on size of JPanel) and only a vertical scrollbar, a Vertical Flowlayout. I have tried the GridLayout but this is not flexible enough as the scroll bars appear for both horizontal and vertical as the amount of columns are set at design time. Do I have to create my own Layout Manager or Scoll Pane or both?
    Craig
  2. #2
  3. Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Feb 2007
    Posts
    1,940
    Rep Power
    3117
    I was running into the exact same problem and found this post. I found a solution here:
    http://coding.derkeiler.com/Archive/...4-03/0816.html

    If the link doesn't work here is the author explaining this custom class to solve this problem. I used the class and it worked great. I assume the OP found another solution since he asked this months ago, but this might be helpful if someone else runs into this post:

    Code:
    FlowLayout is too dumb a LayoutManager for use in containers that need
    to be placed in a JScrollPane (unless you want only horizontal
    scrolling). This is because the preferredLayoutSize value returned by it
    is always the same - irrespective of the actual width of the container.
    (And therefore the preferredSize value returned by the panel would
    always be what is required to place all components in a single row).
    
    Setting the preferredSize value to a hard coded value number is no
    solution either, because the panel will now always return the set
    value irrespective of the components it contains.
    
    Attached below is a modified FlowLayout class that will return a
    variable preferredSize depending on the current width of the container.
    and hence allow you to enable vertical scrolling.
    
    Also, in order to limit your panel width and enable wrapping, it is
    better to make your panel implement the Scrollable interface. Return
    true for the getScrollableTracksViewportWidth() method so that
    horizontal scrolling is disabled. Also return your preferred viewport
    dimension from the getPreferredScrollableViewportSize() method.
    
    BK
    
    /*
      */
    import java.awt.*;
    
    /**
      * A modified version of FlowLayout that allows containers using this
      * Layout to behave in a reasonable manner when placed inside a
      * JScrollPane
            
      * @author Babu Kalakrishnan
      */
    public class ModifiedFlowLayout extends FlowLayout
    {
         public ModifiedFlowLayout()
         {
             super();
         }
    
         public ModifiedFlowLayout(int align)
         {
             super(align);
         }
    
         public ModifiedFlowLayout(int align, int hgap, int vgap)
         {
             super(align, hgap, vgap);
         }
    
         public Dimension minimumLayoutSize(Container target)
         {
             return computeSize(target, false);
         }
    
         public Dimension preferredLayoutSize(Container target)
         {
             return computeSize(target, true);
         }
    
         private Dimension computeSize(Container target, boolean minimum)
         {
             synchronized (target.getTreeLock())
             {
                 int hgap = getHgap();
                 int vgap = getVgap();
                 int w = target.getWidth();
    
                // Let this behave like a regular FlowLayout (single row)
                // if the container hasn't been assigned any size yet
                 if (w == 0)
                     w = Integer.MAX_VALUE;
    
                 Insets insets = target.getInsets();
                 if (insets == null)
                     insets = new Insets(0, 0, 0, 0);
                 int reqdWidth = 0;
    
                 int maxwidth = w - (insets.left + insets.right + hgap * 2);
                 int n = target.getComponentCount();
                 int x = 0;
                 int y = insets.top;
                 int rowHeight = 0;
    
                 for (int i = 0; i < n; i++)
                 {
                     Component c = target.getComponent(i);
                     if (c.isVisible())
                     {
                         Dimension d =
                             minimum ? c.getMinimumSize() :
                                      c.getPreferredSize();
                         if ((x == 0) || ((x + d.width) <= maxwidth))
                         {
                             if (x > 0)
                             {
                                 x += hgap;
                             }
                             x += d.width;
                             rowHeight = Math.max(rowHeight, d.height);
                         } else
                         {
                             x = d.width;
                             y += vgap + rowHeight;
                             rowHeight = d.height;
                         }
                         reqdWidth = Math.max(reqdWidth, x);
                     }
                 }
                 y += rowHeight;
                 return new Dimension(reqdWidth+insets.left+insets.right, y);
             }
         }
    }
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2010
    Posts
    1
    Rep Power
    0

    Updated ModifiedFlowLayout for resizeable containers.


    Thanks for the code. I modified mine slightly to work better with horizontal slider containers. Fixed a small issue with it computing the height too...needed to add a vgap at the beginning. Maybe someone else will find this useful.

    Code:
    /*
      */
    import java.awt.*;
    
    /**
      * A modified version of FlowLayout that allows containers using this
      * Layout to behave in a reasonable manner when placed inside a
      * JScrollPane
            
      * @author Babu Kalakrishnan
      */
    public class ModifiedFlowLayout extends FlowLayout {
       public ModifiedFlowLayout() {
          super();
       }
    
       public ModifiedFlowLayout(int align) {
          super(align);
       }
    
       public ModifiedFlowLayout(int align, int hgap, int vgap) {
          super(align, hgap, vgap);
       }
       
       public Dimension minimumLayoutSize(Container target) {
          // Size of largest component, so we can resize it in
          // either direction with something like a split-pane.
          return computeMinSize(target);
       }
    
       public Dimension preferredLayoutSize(Container target) {
          return computeSize(target);
       }
    
       private Dimension computeSize(Container target) {
          synchronized (target.getTreeLock()) {
             int hgap = getHgap();
             int vgap = getVgap();
             int w = target.getWidth();
    
             // Let this behave like a regular FlowLayout (single row)
             // if the container hasn't been assigned any size yet
             if (w == 0)
                w = Integer.MAX_VALUE;
             
             Insets insets = target.getInsets();
             if (insets == null)
                insets = new Insets(0, 0, 0, 0);
             int reqdWidth = 0;
             
             int maxwidth = w - (insets.left + insets.right + hgap * 2);
             int n = target.getComponentCount();
             int x = 0;
             int y = insets.top + vgap; // FlowLayout starts by adding vgap, so do that here too.
             int rowHeight = 0;
             
             for (int i = 0; i < n; i++) {
                Component c = target.getComponent(i);
                if (c.isVisible()) {
                   Dimension d = c.getPreferredSize();
                   if ((x == 0) || ((x + d.width) <= maxwidth)) {
                      // fits in current row.
                      if (x > 0) {
                         x += hgap;
                      }
                      x += d.width;
                      rowHeight = Math.max(rowHeight, d.height);
                   }
                   else {
                      // Start of new row
                      x = d.width;
                      y += vgap + rowHeight;
                      rowHeight = d.height;
                   }
                   reqdWidth = Math.max(reqdWidth, x);
                }
             }
             y += rowHeight;
             y += insets.bottom;
             return new Dimension(reqdWidth+insets.left+insets.right, y);
          }
       }//computeSize
    
       private Dimension computeMinSize(Container target) {
          synchronized (target.getTreeLock()) {
             int minx = Integer.MAX_VALUE;
             int miny = Integer.MIN_VALUE;
             boolean found_one = false;
             int n = target.getComponentCount();
    
             for (int i = 0; i < n; i++) {
                Component c = target.getComponent(i);
                if (c.isVisible()) {
                   found_one = true;
                   Dimension d = c.getPreferredSize();
                   minx = Math.min(minx, d.width);
                   miny = Math.min(miny, d.height);
                }
             }
             if (found_one) {
                return new Dimension(minx, miny);
             }
             return new Dimension(0, 0);
          }
       }//computeSize
    
    }//ModifiedFlowLayout
    Last edited by greearb; January 18th, 2010 at 06:33 PM. Reason: code high-lighting turned out funky.

IMN logo majestic logo threadwatch logo seochat tools logo