Adam P. Adam P. - 1 month ago 11
Java Question

My Java Swing JPanel centering function does not work. Why?

The "JPanel" in the middle, I would like to move alignment operations to separated function, but it somehow does not work. The operations were by carrying out locally all works well.

desCont = new DesignController();

JPanel centerBox = desCont.createCenterPanel();
this.add(centerBox);


DesignController class source:

public class DesignController {
(...)
public JPanel createCenterPanel(){
JPanel centerPanel = new JPanel();
JPanel hbox = new JPanel();
JPanel vbox = new JPanel();

centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS ));
centerPanel.add(Box.createHorizontalGlue());
centerPanel.add(hbox);
centerPanel.add(Box.createHorizontalGlue());

hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());

return centerPanel;
}
}


UPDATE:



Example file the necessary elements for the reconstruction of the problem:

public class CenterTest {
private JFrame frame;
private static CardLayout cardLayout = new CardLayout();
private JPanel headPanel;
private static JPanel contentPanel;
private JPanel footerPanel;
private static JPanel mainPanel;

private AppConstants appVars;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CenterTest window = new CenterTest();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Create the application.
*/
public CenterTest() {
initialize();
}

/**
* Initialize the contents of the frame.
*/
private void initialize() {
appVars = new AppConstants();

frame = new JFrame();
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setBounds(100, 100, appVars.initWidth, appVars.initHeight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

mainPanel = new JPanel();
frame.getContentPane().add(mainPanel, BorderLayout.CENTER);
mainPanel.setLayout(new BorderLayout(0, 0));

headPanel = new JPanel();
headPanel.setBackground(Color.LIGHT_GRAY);
headPanel.setPreferredSize(new Dimension( appVars.initHeaderPanelWidth, appVars.headerPanelHeight ));
mainPanel.add(headPanel, BorderLayout.NORTH);

contentPanel = new JPanel();
contentPanel.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));
mainPanel.add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(cardLayout);

footerPanel = new JPanel();
footerPanel.setBackground(Color.GREEN);
footerPanel.setPreferredSize(new Dimension(appVars.initFooterPanelWidth, appVars.footerPanelHeight));
mainPanel.add(footerPanel, BorderLayout.SOUTH);

addCard(new CenterPanel(), "center-panel");
}

public static void addCard(JPanel panel, String name){
contentPanel.add(panel, name);
cardLayout.show(contentPanel, name);
}

}

class CenterPanel extends JPanel {

private static final long serialVersionUID = 1L;

/**
* Include DesignController class.
*/
private DesignController desCont;

/**
* Include global variables class.
*/
private AppConstants appVars;

public CenterPanel(){
appVars = new AppConstants();
desCont = new DesignController();

/* ------------ THIS SECTION IS NOT CORRECTLY WORKING ----------------- */
JPanel hBox = desCont.createCenterPanel();
hBox.setBackground(Color.YELLOW);
this.add(hBox);
/* ------------ THIS SECTION IS NOT CORRECTLY WORKING ----------------- */

/* ------------ THIS SECTION IS CORRECTLY WORKING ----------------- */

/*JPanel hbox = new JPanel();
JPanel vbox = new JPanel();
vbox.setBackground(new Color(0, 204, 204));
vbox.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));

setLayout(new BoxLayout(this, BoxLayout.X_AXIS ));
add(Box.createHorizontalGlue());
add(hbox);
add(Box.createHorizontalGlue());

hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());*/

/* ------------ THIS SECTION IS CORRECTLY WORKING ----------------- */
}
}



class DesignController {
private AppConstants appVars = new AppConstants();

public JPanel createCenterPanel(){
JPanel centerPanel = new JPanel();
JPanel hbox = new JPanel();
JPanel vbox = new JPanel();

vbox.setBackground(new Color(0, 204, 204));
vbox.setPreferredSize(new Dimension(appVars.initContentWidth, appVars.initContentHeight));

centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.X_AXIS ));
centerPanel.add(Box.createHorizontalGlue());
centerPanel.add(hbox);
centerPanel.add(Box.createHorizontalGlue());

hbox.setLayout(new BoxLayout(hbox, BoxLayout.Y_AXIS ));
hbox.add(Box.createVerticalGlue());
hbox.add(vbox);
hbox.add(Box.createVerticalGlue());

return centerPanel;
}

}

class AppConstants {
/**
* Define initial width of window <br/>
* <b>900</b>
*/
public int initWidth = 900;

/**
* Define initial height of window <br/>
* <b>600</b>
*/
public int initHeight = 600;


/**
* Define initial width of window header, same as window width <br/>
* <b>900</b>
*/
public int initHeaderPanelWidth = initWidth;

/**
* Define height of windows header panel <br/>
* <b>80</b>
*/
public int headerPanelHeight = 80;



/**
* Define initial width of window footer, same as window width <br/>
* <b>900</b>
*/
public int initFooterPanelWidth = initWidth;

/**
* Define height of windows footer panel <br/>
* <b>50</b>
*/
public int footerPanelHeight = 50;



/**
* Define initial width of content panel, same as window width <br/>
* <b>900</b>
*/
public int initContentWidth = 900;

/**
* Define height of content panel <br/>
* <b>window initial height - (header panel height + footer panel height)</b>
*/
public int initContentHeight = initHeight - (headerPanelHeight + footerPanelHeight);
}



Answer

Your approach is wrong. You can't return the "center panel".

In order to have the panel centered you need a structure like this:

HorizontalPanel
   VerticalPanel
        CenterPanel

The vertical/horizontal panels are wrappers and you need to add the horizontal panel to your frame since it is the parent panel of the components.

If you add the "CenterPanel" to the frame then you will lose the vertical/horizontal wrapper panels because a Swing component can only have a single parent. So the frame becomes the new parent of the "CenterPanel".

So the design of your method needs to be something like:

public static Component centerPanel(Component panelToBeCentered)
{
    JPanel vertical = ...
    vertical.add( panelToBeCentered );

    JPanel horizontal = ...
    horizontal.add( vertical );

    return horizontal;
}

To use the code you do something like:

 JPanel center = new JPanel();
 center.add(...);

 frame.add( DesignController.centerPanel( center ) );

Note when using a BoxLayout you can use the convenience static methods:

Box vertical = Box.createVerticalBox();
Box horizontal Box.createHorizontalBox();

to create a container to hold your components.

Even easier you don't need to use nested boxes. You can just use a GridBagLayout. The default constraints of the GridBagLayout will cause the component to be centered:

JPanel center = new JPanel();
JPanel wrapper = new JPanel( new GridBagLayout() );
wrapper.add(center, new GridBagConstraints());
frame.add( wrapper );