I've made the following layout manager class:
public class MainFrameLayout extends BorderLayout
{
private final JPanel north, center, south;
/**
* Constructor for this layout.
*/
public MainFrameLayout()
{
super();
north = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
center = new JPanel();
center.setLayout(new BoxLayout(center, BoxLayout.Y_AXIS));
south = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
north.setVisible(true);
center.setVisible(true);
south.setVisible(true);
super.addLayoutComponent(north, NORTH);
super.addLayoutComponent(center, CENTER);
super.addLayoutComponent(south, SOUTH);
}
@Override
public void addLayoutComponent(Component comp, Object constraints)
{
if (!(constraints instanceof MainFrameLayoutConstraints))
throw new IllegalArgumentException("Invalid constraints");
switch ((MainFrameLayoutConstraints) constraints)
{
case NORTH:
north.add(comp);
break;
case CENTER:
center.add(comp);
break;
case SOUTH:
south.add(comp);
break;
}
}
}
MainFrameLayoutConstraints
is a generic enum
class with only NORTH
, CENTER
, and SOUTH
variants.
I attempted to use this layout in the following application:
public class MyApplication extends JFrame
{
private final JFormattedTextField caseNumberBox;
public MyApplication()
{
super("A Title Thingy");
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
NumberFormat caseNumberFormat = NumberFormat.getIntegerInstance();
caseNumberBox = new JFormattedTextField(caseNumberFormat);
caseNumberBox.setColumns(20);
this.setLayout(new MainFrameLayout());
this.add(new JLabel("Major Release Case: "), MainFrameLayoutConstraints.NORTH);
this.add(caseNumberBox, MainFrameLayoutConstraints.NORTH);
this.pack();
this.setVisible(true);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
MyApplication app = new MyApplication();
}
}
Why, when I run this application, are my components (the label and text field) invisible even though the call to pack()
sized the window appropriately to fit those fields?
The reason for the behaviour is trying to create components inside the layout manager. While MainFrameLayout
calls super.addLayoutComponent()
for the components it creates, these are not added to the parent component itself. Therefore, the components you add to the frame count for the frame's preferred size calculation, as that's delegated to BorderLayout
which assumes the content pane contains panels you created in the MainFrameLayout
constructor, but they never get drawn as the panels haven't actually been added to the content pane.
A custom layout manager is the wrong tool for what you're trying to achieve. Simply use a nested layout.