4

I'm prgramming a simple input diagram in Swing. I use boxLayout to create a simple GUI of user input. Problem is that creating a horizontal strut between the JPanel of all the labels and the JPanel of the JTextFields causes the whole panel to shift downwards (weird) this is the whole panel:

private JPanel secondCard() {

    //main panel. set the boxlayout
    secondCard = new JPanel();
    secondCard.setLayout(new BoxLayout(secondCard,BoxLayout.Y_AXIS));

    // create vertical strut for looks
    secondCard.add(Box.createVerticalStrut(20));

    // create title. center it.
    JLabel title = new JLabel("Configure main network parameters "); 
    title.setAlignmentX(CENTER_ALIGNMENT);
    secondCard.add(title);

    // create vertical strut for looks
    secondCard.add(Box.createVerticalStrut(20));

    // create panel for the description labels
    JPanel labelPanel = new JPanel();
    labelPanel.setLayout(new BoxLayout(labelPanel,BoxLayout.Y_AXIS));
    labelPanel.setAlignmentX(LEFT_ALIGNMENT);

    JLabel inPut =new JLabel("number of inputs");
    inPut.setAlignmentX(LEFT_ALIGNMENT);
    labelPanel.add(inPut);

    inPut =new JLabel("number of outputs");
    inPut.setAlignmentX(LEFT_ALIGNMENT);
    labelPanel.add(inPut);

    inPut =new JLabel("number of layers");
    inPut.setAlignmentX(LEFT_ALIGNMENT);
    labelPanel.add(inPut);

    JPanel textFieldPanel = new JPanel();
    textFieldPanel.setLayout(new BoxLayout(textFieldPanel,BoxLayout.Y_AXIS));
    textFieldPanel.setAlignmentX(LEFT_ALIGNMENT);

    JTextField inputTextField = new JTextField();
    inputTextField.setAlignmentX(LEFT_ALIGNMENT);
    textFieldPanel.add(inputTextField);
    inputTextField.setMinimumSize(new Dimension(0,0));

    inputTextField = new JTextField();
    inputTextField.setAlignmentX(LEFT_ALIGNMENT);
    textFieldPanel.add(inputTextField);
    inputTextField.setMinimumSize(new Dimension(0,0));

    inputTextField = new JTextField();
    inputTextField.setAlignmentX(LEFT_ALIGNMENT);
    textFieldPanel.add(inputTextField);
    inputTextField.setMinimumSize(new Dimension(0,0));

    textFieldPanel.setMaximumSize(new Dimension(50, labelPanel.getMaximumSize().height));

    JPanel inputPanel = new JPanel();
    inputPanel.setLayout(new BoxLayout(inputPanel,BoxLayout.X_AXIS));
    inputPanel.setAlignmentX(CENTER_ALIGNMENT);

    inputPanel.add(labelPanel);

    //this is the problem strut!! it causes inputPanel to shift downwards 
    inputPanel.add(Box.createHorizontalStrut(20));

    inputPanel.add(textFieldPanel);

    secondCard.add(inputPanel);

    return secondCard;
}

without the strut it looks like: enter image description here

With strut it looks like (I know I suck at picture editing):

enter image description here

hasdrubal
  • 1,024
  • 14
  • 30

3 Answers3

5

You are adding a Box strut to a BoxLayout.

As the javadoc states, createHorizontalStrut(int width):

Creates an invisible, fixed-width component. In a horizontal box, you typically use this method to force a certain amount of space between two components. In a vertical box, you might use this method to force the box to be at least the specified width. The invisible component has no height unless excess space is available, in which case it takes its share of available space, just like any other component that has no maximum height.

As such, it is filling the height between your title JLabel and the bottom of the JPanel.

You might want to consider using Box.createRigidArea(new Dimension(20, height)) instead, where height could be specified or set to the height of labelPanel.

Or, you could reconsider the layout for your JPanel - take a look at the visual guide.

For future reference, if you cannot make sense of your Swing layout, try putting adding a coloured LineBorder to the JComponents you're unsure of. In this case, the Box struts are not JComponents but Components, so you'd have to put them into a JPanel, but this would at least have shown you what space each component was taking up in your top-level JPanel.

amaidment
  • 6,942
  • 5
  • 52
  • 88
  • [`javax.swing.Box`](http://docs.oracle.com/javase/tutorial/uiswing/layout/box.html#filler) is "A lightweight container that uses a BoxLayout object as its layout manager." `Box.Filler` is a static nested class that works quite well with `Box` or `BoxLayout`. – trashgod May 25 '12 at 01:40
3
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I placed the buttonPanel ("previous","next","finish" & "cancel") at contentPane.SOUTH. in the centre of the contentPane I placed a JPanel with cardlayout. The secondCard JPanel is the code shown above. It is the second card of the layout (poor nomenclature, I know). Is that a good aproach? I chose BoxLayout because it is simple and because BorderLayout sucks – hasdrubal May 25 '12 at 10:09
  • @user1111: BorderLayout can work well, especially if used in conjunction with other layouts as mKorbel recommends. 1+ to mKorbel. – Hovercraft Full Of Eels May 25 '12 at 12:07
2

Example of a nested layout, one using BorderLayout, FlowLayout (JPanel's default), and GridBagLayout:

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.util.HashMap;
import java.util.Map;

import javax.swing.*;

public class LayoutFoo {
   private static final String TITLE = "Configure Main Foobar Parameters";
   private static final String[] LABEL_TEXTS = {
      "Number of Spams", "Number of Frapzats", "Number of Zignuts"
   };
   private static final int TEXTFIELD_SIZE = 10;
   private static final Insets WEST_INSETS = new Insets(5, 5, 5, 10);
   private static final Insets EAST_INSETS = new Insets(5, 10, 5, 5);
   private static final int EB_GAP = 5;
   private Map<String, JTextField> textFieldMap = new HashMap<String, JTextField>();

   public JPanel getConfigFooPanel() {
      JPanel textFieldPanel = new JPanel(new GridBagLayout());
      for (int i = 0; i < LABEL_TEXTS.length; i++) {
         addTextAndField(textFieldPanel, LABEL_TEXTS[i], i);
      }

      int blVertGap = 20;
      JPanel borderLayoutPanel = new JPanel(new BorderLayout(0, blVertGap));
      borderLayoutPanel.setBorder(BorderFactory.createEmptyBorder(EB_GAP, EB_GAP,
            EB_GAP, EB_GAP));
      JLabel titleLabel = new JLabel(TITLE, JLabel.CENTER);
      borderLayoutPanel.add(titleLabel, BorderLayout.PAGE_START);
      borderLayoutPanel.add(textFieldPanel, BorderLayout.CENTER);

      JPanel outerWrapperFlowPanel = new JPanel();
      outerWrapperFlowPanel.add(borderLayoutPanel);

      return outerWrapperFlowPanel;      
   }

   public String getFieldText(String labelText) {
      JTextField field = textFieldMap.get(labelText);
      if (field == null) {
         return ""; // ?? throw exception
      } else {
         return field.getText();
      }
   }

   private void addTextAndField(JPanel panel, String text, int i) {
      JLabel label = new JLabel(text, JLabel.LEFT);
      JTextField textField = new JTextField(TEXTFIELD_SIZE);
      textFieldMap.put(text, textField);
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = 0;
      gbc.gridy = i;
      gbc.gridwidth = 1;
      gbc.gridheight = 1;
      gbc.weightx = 1.0;
      gbc.weighty = 1.0;
      gbc.fill = GridBagConstraints.HORIZONTAL;
      gbc.anchor = GridBagConstraints.WEST;
      gbc.insets = WEST_INSETS;
      panel.add(label, gbc);

      gbc.gridx = 1;
      gbc.anchor = GridBagConstraints.EAST;
      gbc.insets = EAST_INSETS;
      panel.add(textField, gbc);
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("LayoutFoo");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new LayoutFoo().getConfigFooPanel());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373