Why don’t size and preferredSize make this label bigger?

Tags: ,



I’m building up a panel that will go in a larger program; the following program still illustrates my question, but it looks a bit more complicated than it absolutely has to because there are places I will add things later.

package sandbox;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class SpacingPlay extends JFrame
{
  private static final long serialVersionUID = 1L;

  public static void main(String[] args)
  {
    SpacingPlay sp = new SpacingPlay();
    sp.setVisible(true);
  }
  
  public SpacingPlay()
  {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel panel = new DragNDropPanel();
    add(panel);
    pack();
  }

  class DragNDropPanel extends JPanel
  {
    private static final long serialVersionUID = 1L;
    
    public DragNDropPanel()
    {
      
      JPanel currentImagePanel    = getCurrentImagePanel();
      JPanel  leftPanel = new JPanel();
      leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.PAGE_AXIS));
      leftPanel.add(currentImagePanel);
      
      // other things will go here; I cut them out to make this simpler.
      
      setLayout(new BorderLayout());
      // put things in a containing panel so that they aren't stretched being in the WEST part of a borderlayout.
      JPanel leftContainingPanel = new JPanel();
      leftContainingPanel.add(leftPanel);
      add(leftContainingPanel, BorderLayout.WEST);
    }
    
    private Component createStandardSpace()
    {
      return Box.createRigidArea(new Dimension(0, 15));
    }
    
    private JPanel getCurrentImagePanel()
    {
      JPanel currentImagePanel = new JPanel();
      currentImagePanel.setLayout(new BoxLayout(currentImagePanel, BoxLayout.PAGE_AXIS));
      
      JLabel currentImageLabel = new JLabel("none");
      currentImageLabel.setBorder(BorderFactory.createDashedBorder(Color.BLUE));
      currentImageLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
      Dimension defaultLabelSize = new Dimension(150,150);      // was expecting this to enlarge the label.
      currentImageLabel.setPreferredSize(defaultLabelSize);
      currentImageLabel.setSize(defaultLabelSize);
      
      JButton clearButton = new JButton("Clear");
      clearButton.setAlignmentX(Component.CENTER_ALIGNMENT);
      clearButton.setBorder(BorderFactory.createLineBorder(Color.GREEN));
      
      currentImagePanel.add(currentImageLabel);
      currentImagePanel.add(createStandardSpace()); 
      currentImagePanel.add(clearButton);
      
      currentImagePanel.setBorder(BorderFactory.createLineBorder(Color.ORANGE));
      return currentImagePanel;
    }
  }

}

I would like the currentImageLabel to be a standard size; I intend for it to get different images put into it during the program, and want it to get these without changing size. My idea was to set a size and preferred size and then scale the images I put there to that size.

However, the defaultLabelSize doesn’t have the effect I thought it would. The label goes into a boxLayout panel; it is added, then a rigid space, then a button. I expected the label to be the default size, not shrunk to min allowed. I’ve put in colored borders to try to understand better what’s happening; it appears that the preferred size is honored for the overall boxLayout panel, but not for the placement of the button below the label. EDIT: In other words, I want the button below the label to be placed below the label when the label is forced to be bigger. But the size I put on the label doesn’t seem to work.

What do I need to do to fix the size of currentImageLabel?

Answer

Not 100% why the label is only sized to the text and not the (hard coded) preferred size. I have not been able to duplicate this behaviour using other combinations of panels and layout managers.

You are using pack so all components should be sized to their preferred sizes.

  Dimension defaultLabelSize = new Dimension(150,150);      // was expecting this to enlarge the label.
  currentImageLabel.setPreferredSize(defaultLabelSize);
  currentImageLabel.setSize(defaultLabelSize);

A few comments:

  1. Setting the size will never work. The layout manager will always override the size/location based on the rules of the layout manager.

  2. The layout manager can use (or ignore) the preferred, minimum and maximum sizes of a component. In the case of the BoxLayout is does attempt to use the preferred size but will respect the minimum and maximum sizes (depending on the available space in the parent panel).

What do I need to do to fix the size of currentImageLabel?

So, to achieve your desired goal of a fixed preferred size for the JLabel you can use:

Dimension defaultLabelSize = new Dimension(150,150);      // was expecting this to enlarge the label.
currentImageLabel.setPreferredSize(defaultLabelSize);
currentImageLabel.setMinimumSize(defaultLabelSize);
currentImageLabel.setMaximumSize(defaultLabelSize);
//currentImageLabel.setSize(defaultLabelSize);

Edit:

was looking for why this doesn’t seem to work

For further clarification, change your original code to:

  currentImageLabel.setPreferredSize(defaultLabelSize);
  System.out.println(currentImageLabel.getPreferredSize());
  System.out.println(currentImageLabel.getMinimumSize());
  System.out.println(currentImageLabel.getMaximumSize());

You will see the min/max sizes of the label are not affected.

From point 2 above you will see that the BoxLayout is respecting the maximum size.

Therefore, by also overriding the maximum size, you allow the label to be displayed at is preferred size.

However, when you calculate the preferred size of the “currentImagePanel” the ( hardcoded) preferred size of the label is used in the preferred size calculation of the panel, so that panel is displayed at the preferred size.

Another note. The “leftContainingPanel” is not needed. You can just add the “leftPanel” to the BorderLayout.WEST, since the BorderLayout will respect the width of the component you add.



Source: stackoverflow