What's the best way to keep JButtons centered in a JPanel using GroupLayout on JPanel resize

StackOverflow https://stackoverflow.com/questions/20557378

  •  01-09-2022
  •  | 
  •  

Question

I originally spent quite a bit of time trying to get the JPanel to re-size when the dialog gets re-sized by grabbing the bottom right corner with the mouse and dragging. I cracked that, I think, but now cannot get the buttons to stay centered. I've included some stripped down code, and I pulled out the other panels (I use the JLayeredPane because there are 5 panels not just the one shown). I saw a fix for this if I was using a JLabel elsewhere on StackOverFlow, but haven't been able to crack this yet. Any help would be appreciated. It seems like I must be missing something really simple. This is my first post so I hope you'll bear with any formatting errors. Thanks....

import java.awt.Color;
import java.awt.Component;
import java.util.logging.Logger;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class mock2Dialog extends JDialog {


private static final long serialVersionUID = 1L;
public static int BUTTON_UNKNOWN = -1;
public static int BUTTON_NO = 1;
public static int BUTTON_YES = 0;

public static int DIALOG_TYPE_YES_NO = 1;

int buttonClicked = BUTTON_UNKNOWN;
int dialogType = 1;
Logger logger = null;

public mock2Dialog() {
    }

public mock2Dialog(java.awt.Frame parent, boolean modal, String title,
        int dialogType, Logger logger) {
    super(parent, modal);
    this.logger = logger;
    this.dialogType = dialogType;
    initComponents(); 
    this.setTitle(title);
    buttonClicked = BUTTON_UNKNOWN;

    getYesButton().setFocusTraversalKeysEnabled(false);
    getNoButton().setFocusTraversalKeysEnabled(false);

    getYesNoPanel().setVisible(false);

    getYesButton().setVisible(false);
    getNoButton().setVisible(false);

    onOpen(this); //this fakes out the system so I can execute from this file       

}//EOM

public void onOpen(Component caller) {
    setLocationRelativeTo(caller);
    prepareOnOpen();
}//EOM

public void prepareOnOpen() {
    getYesNoPanel().setVisible(false);
    getYesButton().setVisible(false);
    getNoButton().setVisible(false);

    if (dialogType == DIALOG_TYPE_YES_NO) {
        getYesNoPanel().setVisible(true);
        getYesButton().setVisible(true);
        getNoButton().setVisible(true);
    } 

    buttonClicked = BUTTON_UNKNOWN;
    if (dialogType == DIALOG_TYPE_YES_NO) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                yesButton.requestFocusInWindow();
            }
        });

    }
    this.setVisible(true);
} //EOM


private void initComponents() {

    msgScrollPane = new JScrollPane();
    msgTextArea = new JTextArea();
    jLayeredPane1 = new JLayeredPane(); //no LayoutManager specified by design of component
    yesNoPanel = new JPanel();
    yesButton = new JButton();
    noButton = new JButton();


    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
    setTitle("Message");

    //msgScrollPane
    msgScrollPane.setBorder(null);

    //msgTextArea
    msgTextArea.setColumns(20);
    msgTextArea.setEditable(false);
    msgTextArea.setFont(new java.awt.Font("Verdana", 0, 14));
    msgTextArea.setRows(5);
    msgTextArea.setWrapStyleWord(true);
    msgTextArea.setBorder(javax.swing.BorderFactory.createEtchedBorder());
    msgTextArea.setOpaque(false);
    msgScrollPane.setViewportView(msgTextArea);

    //YesNoPanel
    yesNoPanel.setBackground(Color.BLUE);
    yesButton.setText("Yes");
    yesButton.setName("yesButton");
    //yesButton.setAlignmentX(CENTER_ALIGNMENT); //thought this might work to center the button within the panel

    noButton.setText("No");
    noButton.setName("noButton");
    //noButton.setAlignmentX(CENTER_ALIGNMENT); //thought this might work to center the button within the panel

    GroupLayout yesNoPanelLayout = new GroupLayout(
            yesNoPanel);
    yesNoPanel.setLayout(yesNoPanelLayout);
    yesNoPanelLayout
            .setHorizontalGroup(yesNoPanelLayout
                    .createParallelGroup(
                            javax.swing.GroupLayout.Alignment.LEADING) //Center doesn't seem to change behaviour
                    .addGroup(
                            yesNoPanelLayout
                                    .createSequentialGroup()
                                    .addGap(146, 146, 146)
                                    .addComponent(yesButton)
                                    .addPreferredGap(
                                            javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(noButton)
                                    .addContainerGap(147, Short.MAX_VALUE)));
    yesNoPanelLayout
            .setVerticalGroup(yesNoPanelLayout
                    .createParallelGroup(
                            javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(
                            yesNoPanelLayout
                                    .createSequentialGroup()
                                    .addContainerGap()
                                    .addGroup(
                                            yesNoPanelLayout
                                                    .createParallelGroup(
                                                            javax.swing.GroupLayout.Alignment.LEADING)
                                                    .addComponent(yesButton)
                                                    .addComponent(noButton))
                                    .addContainerGap(
                                            javax.swing.GroupLayout.DEFAULT_SIZE,
                                            Short.MAX_VALUE)));

    yesNoPanel.setBounds(0, 0, Short.MAX_VALUE, 50); //setting Short.MAX_VALUE will allow the panel to expand.
    jLayeredPane1.add(yesNoPanel, javax.swing.JLayeredPane.DEFAULT_LAYER);


    //main layout for the dialog
    GroupLayout layout = new GroupLayout(
            getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(layout
            .createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(
                    layout.createSequentialGroup()
                            .addComponent(jLayeredPane1,
                                    GroupLayout.DEFAULT_SIZE,
                                    GroupLayout.DEFAULT_SIZE, //400,
                                    Short.MAX_VALUE)
                            .addGap(0, 0, 0))
            .addGroup(
                    layout.createSequentialGroup()
                            .addGap(12, 12, 12)
                            .addComponent(msgScrollPane,
                                    GroupLayout.DEFAULT_SIZE,
                                    376, 
                                    Short.MAX_VALUE).addContainerGap()));
    layout.setVerticalGroup(layout
            .createParallelGroup(GroupLayout.Alignment.LEADING)
            .addGroup(
                    GroupLayout.Alignment.TRAILING,
                    layout.createSequentialGroup()
                            .addContainerGap()
                            .addComponent(msgScrollPane,
                                    GroupLayout.DEFAULT_SIZE,
                                    106, Short.MAX_VALUE)
                            .addPreferredGap(
                                    javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(jLayeredPane1,
                                    GroupLayout.PREFERRED_SIZE,
                                    50,
                                    GroupLayout.PREFERRED_SIZE)));

    pack();
} 

private JLayeredPane jLayeredPane1;
private JScrollPane msgScrollPane;
private JTextArea msgTextArea;
private JButton noButton;
private JButton yesButton;
private JPanel yesNoPanel;

public javax.swing.JScrollPane getMsgScrollPane() {
    return msgScrollPane;
}

public void setMsgScrollPane(javax.swing.JScrollPane msgScrollPane) {
    this.msgScrollPane = msgScrollPane;
}

public javax.swing.JTextArea getMsgTextArea() {
    return msgTextArea;
}

public void setMsgTextArea(javax.swing.JTextArea msgTextArea) {
    this.msgTextArea = msgTextArea;
}

public String getMsgText() {
    return this.msgTextArea.getText();
}

public void setMsgText(String msgText) {
    this.msgTextArea.setText(msgText);
    msgTextArea.setCaretPosition(0);
    msgScrollPane.getVerticalScrollBar().setValue(0);
}

public javax.swing.JButton getNoButton() {
    return noButton;
}

public void setNoButton(javax.swing.JButton noButton) {
    this.noButton = noButton;
}

public javax.swing.JButton getYesButton() {
    return yesButton;
}

public void setYesButton(javax.swing.JButton yesButton) {
    this.yesButton = yesButton;
}

public javax.swing.JPanel getYesNoPanel() {
    return yesNoPanel;
}

public void setYesNoPanel(javax.swing.JPanel yesNoPanel) {
    this.yesNoPanel = yesNoPanel;
}


public static void main(String args[]) {
    /* Create and display the dialog */
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            Logger logger = null;
            int dialogType = 1;
            String title = "Mock Dialog";
            mock2Dialog dialog = new mock2Dialog(
                    new javax.swing.JFrame(), false, title, dialogType,
                    logger);
            dialog.addWindowListener(new java.awt.event.WindowAdapter() {
                @Override
                public void windowClosing(java.awt.event.WindowEvent e) {
                    System.exit(0);
                }
            }); //nested a method in another methods arguments                          

            dialog.setVisible(true);
            dialog.msgTextArea
                    .setText(" Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam sit amet fringilla nunc.\n "
                            + "Duis sem nulla, egestas vel elit vitae, pulvinar semper nunc. Nam in nisi quis turpis pellentesque pulvinar. \n"
                            + "Nulla facilisi. Pellentesque ac rhoncus ante. Mauris ut magna nibh. Ut eget dapibus diam, sed iaculis erat. "
                            + "Vestibulum faucibus neque nisl, non imperdiet libero elementum sed. Fusce molestie eros id ligula consectetur ultrices.");
        }
    });

}
} 
Was it helpful?

Solution

I find GroupLayout to be fine to code by hand, certainly no harder than GridBagLayout, though I can certainly see why it would be a favorite for tools to use. But it is meant for putting things into columns and rows, not for centering buttons. You have the wrong layout manager.

To put a panel in the center of a screen that you want the user to be able to resize (which should be the default), you can put your panel in the BorderLayout.CENTER of a BorderLayout (which is the default layout manager on a JFrame). Now, by default, the panel will also stretch to fit the frame unless you also put some things in the NORTH, SOUTH, EAST, and/or WEST portions of the BorderLayout. Whether this works for you depends on what you're doing.

I also understand you can put the panel to be centered into a GridBagLayout with nothing else in it, and that will center it. It isn't my method, but I mention it for completeness.

If you want a group of buttons to stay centered, first choose a layout manager for a panel to hold the buttons -- grid layout works only if you want the buttons to be the same size, you can use GropuLayout to put them in rows and columns, a BoxLayout can put a string of buttons horizontally or stack them vertically.

Then you can put THAT panel into another panel with a different layout - say, in the SOUTH portion of a BorderLayout - to center them horizontally, or the WEST portion of a BorderLayout to center them vertically. This is what rcamrick is talking about when he mentions "nested panels".

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top