9
votes

enter image description here

I would like to make a gui that looks like the above. right now I have a panel which will hold the name label, name textfield, brith date label and birthday textfield. My question is what would be the best layout manager to use on the panel so that the row of "name components" (lable + textfield) and the row of "birth date components" (lable + textfield), would be evenly spread vertically in the panel.

I thought about using flow layout, but that would result in no gap between the two rows of components. I thought about using a grid layout, but I do not know the gap size between the two rows of components.

A more complicated approach...i thought about putting the name label and textfield in one panel, and the birth date label and textfield in another panel, then make the base panel border layout and set name to be north, birthdate to be south...but then i would still have to make sure the name components are vertically centered in the name panel and birthdate components are vertically centered in the birth date panel.

Any help is appreciated. The goal is to make sure the row of name components and the row of birth date components are vertically spread out, with the name components being centered vertically on the top half, and the birth date components centered vertically on the bottom half. If anything sounds confusing please let me know I'll try to rephrase for a better understanding.

I am using strictly Java swing with eclipse, no GUI builder or anything like that.

4
It is certainly possible to achieve this with the FormLayout of JGoodies, but that is not included in the JDK.Robin

4 Answers

9
votes

I like the MigLayout. In that case, it would be very easy to layout the components as the MigLayout has a table-like behaviour and the components would be arranged in that way. This is described in the QuickStartGuide.

Edit:

Here is a small example:

enter image description here

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;

public class Test {

    private JFrame frame;
    private JTextField nameTextField, birthDateTextField;
    private JLabel nameLabel, birthDateLabel;

    public Test() {
        initComponents();
    }

    public static void main(String args[]) {
        new Test();
    }

    private void initComponents() {
        frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new MigLayout());

        nameTextField = new JTextField(30);
        birthDateTextField = new JTextField(30);
        nameLabel = new JLabel("Name:");
        birthDateLabel = new JLabel("Birth Date:");

        frame.add(nameLabel);
        frame.add(nameTextField, "wrap");
        frame.add(birthDateLabel);
        frame.add(birthDateTextField);
        frame.pack();
        frame.setVisible(true);
    }
}
3
votes

I highly recommend you stay away from layouts designed to be automated by a layout manager --they can be flexible but they tend to be used as a hammer, a very awkward one that takes a lot of finess if you want components to resize in a natural way.

Learning to use layout managers is a bit of an art. You don't pick just one and use it for every problem, instead you take a few different types and nest them in a way that looks like your data.

In your case I think you'd get along pretty well with 3 flow layouts, two horizontal contained in one vertical, that kind of GUI is exactly what flowLayout was made for and you won't have to add any fiddling with parameters.

By the way, many problems can be solved by nesting Border and Flow layouts--Border can be exceptionally useful because of the way the middle acts to take as much space as it can, but leaving the 4 sides as much room as they need--in fact BorderLayout often only has 2 or 3 areas filled--but may easily nest other Border or flow layouts. These lead to GUIs that require very little placement specifics but still resize naturally.

EDIT: Here is some working code of two flow layouts nested in a box layout.

It's groovy (not java) but the difference is purely syntax--with less clutter.

Note the simplicty and lack of numbers to invent--it just works pretty much like you'd expect.

import javax.swing.*
import java.awt.*

f=new JFrame()
f.setSize(300,200)
p=f.getContentPane()
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS))
p.add(panel("Button 1"))
p.add(panel("Button 2"))
f.show()

void addPanel(name) {
   def child=new JPanel()
   child.add(new JButton(name))
   child.add(new JTextField(20))
   return child
}
2
votes

I personally like GridBagLayout.

Here is an example to demonstrate:

enter image description here

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

public class Test {

    private JFrame frame;
    private JTextField nameTextField, birthDateTextField;
    private JLabel nameLabel, birthDateLabel;

    public Test() {
        initComponents();
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                        if ("Nimbus".equals(info.getName())) {
                            UIManager.setLookAndFeel(info.getClassName());
                            break;
                        }
                    }
                } catch (Exception e) {
                    // If Nimbus is not available, you can set the GUI to another look and feel.
                }
                new Test();
            }
        });
    }

    private void initComponents() {
        frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new GridBagLayout());

        nameTextField = new JTextField(30);
        birthDateTextField = new JTextField(30);
        nameLabel = new JLabel("Name:");
        birthDateLabel = new JLabel("Birth Date:");

        GridBagConstraints gc = new GridBagConstraints();
        gc.fill = GridBagConstraints.HORIZONTAL;
        gc.insets = new Insets(10, 10, 10, 10);

        gc.gridx = 0;
        gc.gridy = 0;
        frame.add(nameLabel, gc);

        gc.gridx = 1;
        gc.gridy = 0;
        frame.add(nameTextField, gc);

        gc.gridx = 0;
        gc.gridy = 1;
        frame.add(birthDateLabel, gc);

        gc.gridx = 1;
        gc.gridy = 1;
        frame.add(birthDateTextField, gc);

        frame.pack();
        frame.setVisible(true);
    }
}
1
votes

GroupLayout suits your needs. Take a look at it. It has the ability to auto-create gaps (or you can manage your own)and it's great for creating forms. It works either horizontally or vertically.