1

Trying to build about this GUI in Swing:

enter image description here

In my MainFrame i set a GridLayout like that to achieve 1 row, 2 columns:

setLayout(new GridLayout(1, 2));

In the Left Column i figures i would need a GridBagLayout as in the right column. Normal GridLayout doesn't work anymore because i want different sizes of each row. For the left column i tried this:

GridBagConstraints gbc = new GridBagConstraints();

    mapPanel = new MapPanel(map);
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridheight = 10;
    add(mapPanel, gbc);

    controlPanel = new JPanel();
    controlPanel.add(new JButton("Test"));
    controlPanel.add(new JButton("Test 2"));
    controlPanel.add(new JButton("Test 3"));
    controlPanel.add(new JButton("Test 4"));
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.gridheight = 1;
    add(controlPanel, gbc);

    logPanel = new LogPanel();
    gbc.fill = GridBagConstraints.BOTH;
    gbc.gridx = 0;
    gbc.gridy = 2;
    gbc.gridheight = GridBagConstraints.REMAINDER;
    add(logPanel, gbc);

This however will result in everything "packed together" in the left column. It won't expand to the 100% height and 50% width the column has. How can i achieve a GUI as in the picture?

Thanks!

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Did you experiment with `setPreferredSize(Dimension)` of the components that you layout? This property is closely related to how layout managers present the result. – Hummeling Engineering BV Jul 05 '15 at 19:54
  • @HummelingEngineering See [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?](http://stackoverflow.com/q/7229226/418556) (Yes.) – Andrew Thompson Jul 05 '15 at 20:21
  • @AndrewThompson I agree it's better not to tweak a component's preferred size, but layout managers tend to use them, even when not set by 'us'. My comment was pointing in that direction... hope my answer is a little better. – Hummeling Engineering BV Jul 05 '15 at 20:28
  • *"I agree it's better not to tweak a component's preferred size,"* The advice in that thread does not say not to 'tweak' them, just not to call **set.** If necessary, **override** the default method, but it is **not** necessary here. An empty border can pad a label, and a text field has the `setColumns(int)` method to suggest a size. **Trying to guess the required size of a component will result in a fragile GUI.** – Andrew Thompson Jul 05 '15 at 20:37
  • @AndrewThompson with "tweak" I actually meant "set", which might have been better in the first place. – Hummeling Engineering BV Jul 05 '15 at 20:40

3 Answers3

1

Look at JNodeLayout. RectNode is exactly what you Need.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;

import com.smartg.swing.layout.JNodeLayout;
import com.smartg.swing.layout.LayoutNode.RectNode;

public class RectNodeDemo {

    public static void main(String[] args) {

        String rootName = "root";
        RectNode root = new RectNode(rootName);
        JNodeLayout layout = new JNodeLayout(root);
        layout.setHgap(1);
        layout.setVgap(1);


        JPanel target = new JPanel();
        target.setBorder(new EmptyBorder(10, 10, 10, 10));

        target.setLayout(layout);

        addPanel(target, root, new Rectangle2D.Double(0, 0, .5, .5));
        addPanel(target, root, new Rectangle2D.Double(0, .5, .5, .1));
        addPanel(target, root, new Rectangle2D.Double(0, .6, .5, .4));  

        addPanel(target, root, new Rectangle2D.Double(.5, 0, .5, .9));
        addPanel(target, root, new Rectangle2D.Double(.5, .9, .5, .1));

        layout.syncNodes();

        JFrame frame = new JFrame();

        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(target, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }

    static void addPanel(JPanel target, RectNode node, Rectangle2D r) {
        JPanel p = new JPanel();
        target.add(p);
        p.setBorder(new LineBorder(Color.BLACK, 1));
        node.add(p, r);
    }
}
andronix
  • 124
  • 9
1

You could use the Relative Layout. This layout allows you to specify the relative sizes of each component.

To create your panel on the left the code would be something like:

RelativeLayout rl = new RelativeLayout(RelativeLayout.Y_AXIS);
rl.setFill( true );
JPanel left = new JPanel( rl );
left.add(panel1, new Float(50));
left.add(panel2, new Float(10));
left.add(panel3, new Float(40));
camickr
  • 321,443
  • 19
  • 166
  • 288
0

Using only GridBagLayout will suffice.

By setting gbc.gridheight = 10 you tell GridBag to use 10 rows for the component. (Similar to rowspan in HTML.) This, however, says nothing about the actual height of the component since rows don't have a fixed height. Consequently, this constraint doesn't have any effect when you're only using a single column. The name of the constraint is IMHO confusing.

Use GridBagConstraints.weightx and GridBagConstraints.weighty to specify where extra space should go. See How to Use GridBagLayout for more.

In combination with component's preferred sizes you'll be able to obtain a panel that will show your components when the panel is small and distribute extra space when the panel is 'too big'.

Though, as Andrew Thompson pointed out, using setPreferredSize() is not a very good way to go. Often, components already have their preferred size just fine as constructed. Just play around with all of GridBagConstraints and see what happens.

This might in the end be a better looking solution.