How can I center a JButton in a JPanel using the default FlowLayout?

364 Views Asked by At

I'm trying to center a JButton in a JPanel using the default FlowLayout. Here is my code:

import javax.swing.*;
import java.awt.*;
public class CoinFlip {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Coin Flip");
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton coinFlipButton = new JButton("Flip Coin");
        coinFlipButton.setSize(100, 100);
        JPanel coinFlipPanel = new JPanel();
        coinFlipPanel.setSize(500, 100);
        coinFlipPanel.setBackground(Color.GRAY);
        coinFlipPanel.add(coinFlipButton);
        JTextArea coinFlipResults = new JTextArea();
        coinFlipResults.setSize(500, 200);
        frame.getContentPane().add(coinFlipPanel);
        frame.getContentPane().add(coinFlipResults);
        frame.setVisible(true);
    }
}

How can I center the JButton (coinFlipButton) in the JPanel (coinFlipPanel)? I've tried using FlowLayout.CENTER but that makes the button increase in size so that it takes up all the space.

2

There are 2 best solutions below

2
markspace On

I double checked with the docs and FlowLayout does have an option to center its components, so mea culpa on that. But otherwise you just kind of have to read the tutorials on the various components and their layouts, and experiment a bit.

One very important point is that jframe.getContentPane().add() for a default JFrame uses a layout that only admits one single component. If you want more than one, you have to use a second component like a JPanel with a Grid or Flow layout. By calling that method twice you're just replacing the previous component. Please go read the tutorial on JFrames and BorderLayout.

Anyway I made a quick program that does something like what you want. I added your text area to a ScrollPane because that's another way of dealing with the main content pane of a JFrame. And when I added the JPanel with the button I added it to the SOUTH part of the BorderLayout, because that's how you display more than one component with BorderLayout. (Tutorial again.)

public class JFrameBorderWithButton {
   public static void main( String[] args ) {
      SwingUtilities.invokeLater( JFrameBorderWithButton::newGui );
   }
   private static void newGui() {
      JFrame frame = new JFrame();
      
      JTextArea text = new JTextArea(5, 40);
      JScrollPane scroll = new JScrollPane( text );
      frame.add( scroll );
      JPanel panel = new JPanel( new FlowLayout( FlowLayout.CENTER ) );
      JButton button = new JButton( "Press Me" );
      panel.add(  button );
      frame.add( panel, BorderLayout.SOUTH );
      
      frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      frame.pack();
      frame.setLocationRelativeTo( null );
      frame.setVisible( true );
   }
}
3
Ryan On

In my experience, the simple layouts are rarely worthwhile. use something like GridBagLayout

public static void main(String [] args) throws IOException {
    JFrame frame = new JFrame("Coin Flip");
    JTextArea textArea = new JTextArea();
    JScrollPane textScroll = new JScrollPane(textArea);
    Action flipAction = new AbstractAction("Flip Coin!") {
        private Random random = new Random();
        
        @Override
        public void actionPerformed(ActionEvent e) {
            if (!textArea.getText().isEmpty()) {
                textArea.append(System.lineSeparator());
            }
            
            if (random.nextBoolean()) {
                textArea.append("Heads!");
            } else {
                textArea.append("Tails!");
            }
        }
    };
            
    JButton flipButton = new JButton(flipAction);
    
    frame.setLayout(new GridBagLayout());
    frame.setPreferredSize(new Dimension(175, 500));
    frame.add(flipButton, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
    frame.add(textScroll, new GridBagConstraints(0, 1, 1, 3, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(4, 4, 4, 4), 0, 0));
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
}