0

If I use GridLayout or BoxLayout for bunch of JTextField and JLabel pairs it will equally split are of JPanel among the text-fields.

it looks like this:

enter image description here

What I want looks like this ( with text-fields squeezed to the top ):

enter image description here

and I was able to achive that following this answer. The code is:

public void forceSize( int szx, int szy, JComponent comp ){
    comp.setPreferredSize( new Dimension( szx, szy ) );
    comp.setMaximumSize  ( new Dimension( szx, szy ) );
    comp.setMinimumSize  ( new Dimension( szx, szy ) );
};

public void addLabeledBox( String label_str, JTextField valField, JPanel labelPane, JPanel valuePane ){
    JLabel label  = new JLabel( label_str );
    label.setLabelFor( valField );
    labelPane.add( label    );
    forceSize( 100, 20, label );
    forceSize( 100, 20, valField );
    valuePane.add( valField );
}

public JComponent makeCityPanel( ){

    //JPanel labelPane = new JPanel( new GridLayout(0,1) );
    //JPanel valuePane = new JPanel( new GridLayout(0,1) );

    JPanel labelPane = new JPanel( ); labelPane.setLayout( new BoxLayout( labelPane, BoxLayout.Y_AXIS )  );
    JPanel valuePane = new JPanel( ); valuePane.setLayout( new BoxLayout( valuePane, BoxLayout.Y_AXIS )  );

    //panel.setLayout(new GridBagLayout());
    //panel.setLayout(new GridBagLayout());

    name_field = new JTextField( );
    addLabeledBox( "name",       name_field,         labelPane, valuePane );

    ix_field = new JFormattedTextField( NumberFormat.getNumberInstance() );
    addLabeledBox( "ix",         ix_field,         labelPane, valuePane);

    iy_field = new JFormattedTextField( NumberFormat.getNumberInstance() );
    addLabeledBox( "iy",         iy_field,         labelPane, valuePane);

    factorySpace_field = new JFormattedTextField( NumberFormat.getNumberInstance() );
    addLabeledBox( "FactorySpace",  factorySpace_field,         labelPane, valuePane);

    storeSpace_field = new JFormattedTextField( NumberFormat.getNumberInstance() );
    addLabeledBox( "StoreSapce",    storeSpace_field,         labelPane, valuePane );

    //JScrollPane cityPanel = new  JScrollPane( ); 
    JPanel cityPanel = new JPanel(new GridLayout(1,0));
    cityPanel.add( labelPane );
    cityPanel.add( valuePane );
    cityPanel.setSize( 100 , 100 );

    return cityPanel;
}

However, I have feeling that this is not the correct way. ( Also here they say that it is bad ).

So is there a better way?

Community
  • 1
  • 1
Prokop Hapala
  • 2,424
  • 2
  • 30
  • 59

3 Answers3

2

Another way is to nest panels with different layout managers:

  1. Make the layout of your "main" panel a BorderLayout and add this panel to the tabbed pane.
  2. Create a second "child" panel using your GridLayout and add your components to the panel.
  3. Add the "child" panel to the BorderLayout.PAGE_Start of the "main" panel. This will respect the preferred height of the panel.

Or you can always use a GridBagLayout. It is more involved because you need to specify constraints for each component, but you can get your desired effect with a single panel. Read the section from the Swing tutorial on How to Use GridBagLayout for more information and working examples.

camickr
  • 321,443
  • 19
  • 166
  • 288
1

A great layout to use is MigLayout.

Here is a bit of code which achieves what you want using the layout.

import javax.swing.*;
import java.awt.*;
import net.miginfocom.swing.MigLayout;

public class SimpleGUI
{
    public JFrame myMainWindow = new JFrame("City View");

    JPanel guiPanel = new JPanel();

    JLabel name = new JLabel("Name");
    JLabel ix = new JLabel("ix");
    JLabel iy = new JLabel("iy");
    JLabel factorySpace = new JLabel("Factory Space");
    JLabel storeSpace = new JLabel("Store Space");
    JTextField t1 = new JTextField();
    JTextField t2 = new JTextField();
    JTextField t3 = new JTextField();
    JTextField t4 = new JTextField();
    JTextField t5 = new JTextField();

    int fontMetrics;
    FontMetrics fM;

    public void runGUI()
    {
        myMainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        myMainWindow.setLayout(new GridLayout(1,1));

        createTestPanel();

        myMainWindow.getContentPane().add(guiPanel);

        myMainWindow.setVisible(true);
        myMainWindow.pack();
        myMainWindow.setMinimumSize(new Dimension(myMainWindow.getBounds().getSize()));
    }

    public void createTestPanel()
    {
        MigLayout layout = new MigLayout("wrap 2", "[grow]");
        guiPanel.setLayout(layout);

        fM = name.getFontMetrics(name.getFont());
        fontMetrics = fM.stringWidth("Name");
        name.setSize(fontMetrics+10,25);
        guiPanel.add(name);

        guiPanel.add(t1,"growx, width 100:100:");

        fM = ix.getFontMetrics(ix.getFont());
        fontMetrics = fM.stringWidth("ix");
        ix.setSize(fontMetrics+10,25);
        guiPanel.add(ix);

        guiPanel.add(t2,"growx, width 100:100:");

        fM = iy.getFontMetrics(iy.getFont());
        fontMetrics = fM.stringWidth("iy");
        iy.setSize(fontMetrics+10,25);
        guiPanel.add(iy);

        guiPanel.add(t3,"growx, width 100:100:");

        fM = factorySpace.getFontMetrics(factorySpace.getFont());
        fontMetrics = fM.stringWidth("Factory Space");
        factorySpace.setSize(fontMetrics+10,25);
        guiPanel.add(factorySpace);

        guiPanel.add(t4,"growx, width 100:100:");

        fM = storeSpace.getFontMetrics(storeSpace.getFont());
        fontMetrics = fM.stringWidth("Store Space");
        storeSpace.setSize(fontMetrics+10,25);
        guiPanel.add(storeSpace);

        guiPanel.add(t5,"growx, width 100:100:");
    }

    public static void main(String[] args)
    {
        SimpleGUI sG = new SimpleGUI();
        sG.runGUI();
    }   
}

However when you resize this it might look better if when adding the labels you use something like this.

JLabel someLabel = new JLabel("something");

...
MigLayout layout = new MigLayout("wrap 2", "[right][grow]");
guiPanel.setLayout(layout);

guiPanel.add(someLabel,"grow");

Which will give a GUI which looks like this.

Right alligned labels

Some example code for this would be

import javax.swing.*;
import java.awt.*;
import net.miginfocom.swing.MigLayout;

public class SimpleGUI
{
    public JFrame myMainWindow = new JFrame("City View");

    JPanel guiPanel = new JPanel();

    JLabel name = new JLabel("Name");
    JLabel ix = new JLabel("ix");
    JLabel iy = new JLabel("iy");
    JLabel factorySpace = new JLabel("Factory Space");
    JLabel storeSpace = new JLabel("Store Space");
    JTextField t1 = new JTextField();
    JTextField t2 = new JTextField();
    JTextField t3 = new JTextField();
    JTextField t4 = new JTextField();
    JTextField t5 = new JTextField();

    public void runGUI()
    {
        myMainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        myMainWindow.setLayout(new GridLayout(1,1));

        createTestPanel();

        myMainWindow.getContentPane().add(guiPanel);

        myMainWindow.setVisible(true);
        myMainWindow.pack();
        myMainWindow.setMinimumSize(new Dimension(myMainWindow.getBounds().getSize()));
    }

    public void createTestPanel()
    {
        MigLayout layout = new MigLayout("wrap 2", "[right][grow]");
        guiPanel.setLayout(layout);

        guiPanel.add(name);
        guiPanel.add(t1,"growx, width 100:100:");
        guiPanel.add(ix);
        guiPanel.add(t2,"growx, width 100:100:");
        guiPanel.add(iy);
        guiPanel.add(t3,"growx, width 100:100:");
        guiPanel.add(factorySpace);
        guiPanel.add(t4,"growx, width 100:100:");
        guiPanel.add(storeSpace);
        guiPanel.add(t5,"growx, width 100:100:");
    }

    public static void main(String[] args)
    {
        SimpleGUI sG = new SimpleGUI();
        sG.runGUI();
    }   
}
Dan
  • 7,286
  • 6
  • 49
  • 114
0

This looks to me like a classic case for GroupLayout. Unfortunately, the tutorial for GroupLayout is rather overly fond of 'chaining' method calls together, but if you go through it once you should be able to do yours, which is a fairly simple case.

The basic idea is that you add each component once to a vertical layout and once to a horizontal layout; think of it as creating rows columns and rows. Once nice thing about this as compared to GridLayout is that the layout and field 'columns' don't need to be the same width.

arcy
  • 12,845
  • 12
  • 58
  • 103