GridBagLayout: equally distributed cells
Asked Answered
B

5

13

Is it possible to completely emulate the behavior of a GridLayout with the GridBagLayout manager?

Basically, I have a 8x8 grid in which each cell should have the same width and height. The GridLayout automatically did this. But I want to add another row and column to the grid which size is not the same as the other ones. That row/column should take up all the remaining space that might be left over (because the available size couldn't be equally distributed into 8 cells). Is that even possible, or do I – again – have to use a different layout manager?

edit

Here is a simple graphic of what I want to achieve, simplified to just 4 cells: Problem graphic

The colored cells are the ones I added to the actual grid (gray) which has cells with the same height and width x. So the grid's height and width is 4*x. I now want the additional cells to have the necessary width/height (minimumSize) plus the rest of the available width/height from the full size.

If the whole panel's size is changed, the gray grid cells should again take up as much as space as possible.

Biology answered 12/9, 2010 at 15:35 Comment(0)
B
-2

After trying many different things with the built-in layout managers, I decided to create a custom layout manager for this problem as well. I didn't do it yet, as I didn't have the time to continue with this project, but when I have it done, I'll make sure to post the layout manager code here, so that anyone interested in a similar solution can use it.

edit

didxga reminded me in the comments that I wanted to post my solution. However, after digging out the project from back then and looking at it, I actually cannot post my solution because it turns out that I never got to creating it!

It was a uni project that finished official mid September 2010. We actually wanted to continue working on it afterwards, which is probably why I said that I would post it (as that was one thing I wanted to improve), but we never really got around doing it – sadly. Instead I simply left out those extra column and row (which was meant as a label for the rows/columns btw).

So yeah, I’m terribly sorry that I cannot post a layout that does what I initially wanted… :( Maybe if there are enough requesting such a layout, I would create it, but as of now, I’m not really willing to dive into Java layouting again ;)

Biology answered 2/10, 2010 at 17:49 Comment(4)
You forgot to post it, didn't you? :)Harbot
@Harbot Good point, I totally forgot about this. I’ll try to dig that one out, and edit my answer :)Biology
+1 I :-) don't understand :-) whats going on, simple without any issue with GridBadLayout, SpringLayout or e.g., eeeeght especially alive too old thread by downvoting (some changes in LayoutManagers APIs)Rappel
@Rappel making your own LayoutManager is almost invariably a bad idea. It tends to work except when it doesn't, e.g. when you change surrounding layout constraints, or when a new version of Swing assumes more things that a LayoutManager does that the home-cooked LayoutManager doesn't observer - and you won't notice except in the corner cases where the new interpretation actually matters. It's a good way to make your code brittle, unless you're invested into keeping the LayoutManager up with all news about Swing.Putty
R
3

set weightx and weighty of GridBagConstraints of the fixed cells to 0 and the fill to NONE. For the floating cells set fill to BOTH, for the floating cells that should expand only horizontally set weightx to 1 and for the vertically expanding ones set weighty to 1.

The cells only expand if they have any content, so you need to fill it with something. I chose JLabels and set fixed dimensions for the labels in the fixed cells. On resize you need to recalculate the dimensions and call invalidate() to recalculate the layout.

Here is an example for a w x h grid:

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GridBag {
    public static void main(String[] args) {
        final JFrame f = new JFrame("Gridbag Test");
        final Container c = f.getContentPane();
        c.setLayout(new GridBagLayout());

        final Dimension dim = new Dimension(70, 70);
        final int w = 4;
        final int h = 4;
        final JLabel[] yfloating = new JLabel[w];
        final JLabel[] xfloating = new JLabel[h];
        final JLabel[][] fixed = new JLabel[w][h];

        // adding the vertically floating cells
        final GridBagConstraints gc = new GridBagConstraints();
        gc.fill = GridBagConstraints.BOTH;
        gc.weightx = 0.0;
        gc.weighty = 1.0;
        for(int i = 0; i < w; ++i) {
            yfloating[i] = new JLabel("floating " + i);
            yfloating[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
            yfloating[i].setHorizontalTextPosition(JLabel.CENTER);
            yfloating[i].setVerticalTextPosition(JLabel.CENTER);
            gc.gridy = 0;
            gc.gridx = i+1;
            c.add(yfloating[i], gc);
        }

        // adding the horizontally floating cells
        gc.fill = GridBagConstraints.BOTH;
        gc.weightx = 1.0;
        gc.weighty = 0.0;
        for(int i = 0; i < w; ++i) {
            xfloating[i] = new JLabel("floating " + i);
            xfloating[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
            xfloating[i].setHorizontalTextPosition(JLabel.CENTER);
            xfloating[i].setVerticalTextPosition(JLabel.CENTER);
            gc.gridy = i+1;
            gc.gridx = 0;
            c.add(xfloating[i], gc);
        }

        // adding the fixed cells
        gc.fill = GridBagConstraints.NONE;
        gc.weightx = 0.0;
        gc.weighty = 0.0;
        for(int i = 0; i < w; ++i) {
            for(int j = 0; j < h; ++j) {
                fixed[i][j] = new JLabel("fixed " + i);
                fixed[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
                fixed[i][j].setMaximumSize(dim);
                fixed[i][j].setMinimumSize(dim);
                fixed[i][j].setPreferredSize(dim);

                gc.gridx = i+1;
                gc.gridy = j+1;
                c.add(fixed[i][j], gc);
            }
        }

        c.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                final Component comp = e.getComponent();
                final int newSize = Math.min(comp.getHeight() / h, comp.getWidth() / w);
                final Dimension newDim = new Dimension(newSize, newSize);
                for(int i = 0; i < w; ++i) {
                    for(int j = 0; j < h; ++j) {
                        fixed[i][j].setMaximumSize(newDim);
                        fixed[i][j].setMinimumSize(newDim);
                        fixed[i][j].setPreferredSize(newDim);
                    }
                }
                comp.invalidate();
            }
        });

        f.pack();
        f.setVisible(true);
    }
}
Respectively answered 14/9, 2010 at 4:26 Comment(0)
P
1

If you're not tied to the GridBagLayout necessarily, you should look into the MigLayout library. You can do something along the lines of:

MigLayout layout = new MigLayout(
        "",         // Layout Constraints
        "[10][10][10][10]", // Column constraints
        "[10][10][10][10]");  // Row constraints
Patty answered 1/10, 2010 at 2:35 Comment(1)
After reading the quick start guide for this layout manager, I think this is basically what GridBagLayout wishes it was. It works like GridBagLayout, but it seems much more simple and well-defined.Unskillful
M
0

All values are set in the GridBagConstraints.

If you want your 8x8 grid fixed, you can set the ipadx and ipady values.

Then set the weightx and weighty values of your new row/column to 1.0 and set fill to FULL.

Your extra row/column will expand with the space that is left over.

If you want the 8x8 grid to expand as well, that is more complicated. You can adjust the ipadx and ipady values in addition to the weightx and weighty values. Or make a panel for the 8x8 grid and use a GridLayout in there. Use your GridBagLayout on the panel and the additional row/column.

Manufacture answered 12/9, 2010 at 15:42 Comment(2)
Yes, I want the actual grid to expand as necessary, with 8 cells per row/column equal size and the 9th cell some minimum width/height + the rest of the available width/height. I'm not sure if the extra panel will work, as the additional row should have 9 cells with the same width as the rest of the grid, and the additional column 9 cells with the same height. Basically the additional row/column is supposed to contain labels for the cells.Biology
Set fill to FULL? There is no FULL constant in GridBagConstraints (and no FILL neither).Lanthanum
T
0

Is there a reason you're not doing this in a JTable? Seems like just the sort of thing it's made for. With the appropriate cell renderer you can put anything you want in the cells.

http://www.java2s.com/Code/Java/Swing-Components/TableRowHeaderExample.htm

Triggerfish answered 2/10, 2010 at 16:46 Comment(0)
B
-2

After trying many different things with the built-in layout managers, I decided to create a custom layout manager for this problem as well. I didn't do it yet, as I didn't have the time to continue with this project, but when I have it done, I'll make sure to post the layout manager code here, so that anyone interested in a similar solution can use it.

edit

didxga reminded me in the comments that I wanted to post my solution. However, after digging out the project from back then and looking at it, I actually cannot post my solution because it turns out that I never got to creating it!

It was a uni project that finished official mid September 2010. We actually wanted to continue working on it afterwards, which is probably why I said that I would post it (as that was one thing I wanted to improve), but we never really got around doing it – sadly. Instead I simply left out those extra column and row (which was meant as a label for the rows/columns btw).

So yeah, I’m terribly sorry that I cannot post a layout that does what I initially wanted… :( Maybe if there are enough requesting such a layout, I would create it, but as of now, I’m not really willing to dive into Java layouting again ;)

Biology answered 2/10, 2010 at 17:49 Comment(4)
You forgot to post it, didn't you? :)Harbot
@Harbot Good point, I totally forgot about this. I’ll try to dig that one out, and edit my answer :)Biology
+1 I :-) don't understand :-) whats going on, simple without any issue with GridBadLayout, SpringLayout or e.g., eeeeght especially alive too old thread by downvoting (some changes in LayoutManagers APIs)Rappel
@Rappel making your own LayoutManager is almost invariably a bad idea. It tends to work except when it doesn't, e.g. when you change surrounding layout constraints, or when a new version of Swing assumes more things that a LayoutManager does that the home-cooked LayoutManager doesn't observer - and you won't notice except in the corner cases where the new interpretation actually matters. It's a good way to make your code brittle, unless you're invested into keeping the LayoutManager up with all news about Swing.Putty

© 2022 - 2024 — McMap. All rights reserved.