JButtons inside JPanels, fill up the whole panel

2019-07-20 02:52发布

问题:

I've been struggling to set a specific size to a button inserted into a JPanel with a GridLayout.

The button always fills up the whole panel, whereas if I remove the gridlayout, the button won't have the same behavior.

any hints?

package panels;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;


public class ColorDisplay {

private final int X = 100; 
private final int Y = 100;
private final Dimension PANEL_SIZE = new Dimension(500,500);
private JTextField textRed;
private JTextField textGreen;
private JTextField textBlue;
private JLabel labelText, labelRed, labelGreen, labelBlue;
private JPanel displayPanel;
private JPanel textPanel;
private JPanel buttonPanel;
private JButton button;
private final Font font = new Font("Arial", Font.PLAIN, 22);

public static void main(String[] args) {
    // TODO Auto-generated method stub

    new ColorDisplay();


}
public ColorDisplay(){
    JFrame mainFrame = new JFrame();

    // make sure the program exits when the frame close
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setTitle("Color Display");
    mainFrame.setLocation(X,Y);
    mainFrame.setPreferredSize(PANEL_SIZE);

    // ensure an elastic layout
    mainFrame.setLayout(new GridLayout(3, 1));

    mainFrame.setLocationByPlatform(true);

    mainFrame.add(getColorPanel());
    mainFrame.add(getTextPanel());
    mainFrame.add(getButtonPanel());

    mainFrame.pack();
    mainFrame.setVisible(true);

}

public JPanel getColorPanel(){
    displayPanel = new JPanel(new BorderLayout());
    labelText = new JLabel("Color Display", JLabel.CENTER);
    Font fontColorDisplay = new Font("Arial", Font.PLAIN, 42);
    labelText.setFont(fontColorDisplay);

    displayPanel.add(labelText);

    return displayPanel;
}

public JPanel getTextPanel(){
    textPanel = new JPanel(new GridLayout(2,3));
    labelRed = new JLabel("Red", JLabel.CENTER);
    labelGreen = new JLabel("Green", JLabel.CENTER);
    labelBlue = new JLabel("Blue", JLabel.CENTER);
    textRed = new JTextField();
    textGreen = new JTextField();
    textBlue = new JTextField();

    labelRed.setFont(font);
    labelGreen.setFont(font);
    labelBlue.setFont(font);
    textRed.setFont(font);
    textGreen.setFont(font);
    textBlue.setFont(font);

    textPanel.add(labelRed);
    textPanel.add(labelGreen);
    textPanel.add(labelBlue);
    textPanel.add(textRed);
    textPanel.add(textGreen);
    textPanel.add(textBlue);

    return textPanel;
}

public JPanel getButtonPanel(){

    buttonPanel = new JPanel(new BorderLayout());
    button = new JButton("Display Color");
    button.addActionListener(new ButtonListener ()); // Add event handler
    button.setFont(font);
    button.setPreferredSize(new Dimension(100, 100));

    buttonPanel.add(button);
    return buttonPanel;

}

private int getColor(){

    String colorCode = textRed.getText() + textGreen.getText() + textBlue.getText();
    return Integer.parseInt(colorCode);
}

private boolean validateColor(String textValue){
    boolean isValid = false;
    try {
        int num1 = Integer.parseInt(textValue);
        if (num1 >= 0 && num1 <= 255)
            isValid = true;
        else
        {
            isValid = false;
            JOptionPane.showConfirmDialog(null, "Please enter numbers between 0 and 255", "Error", JOptionPane.PLAIN_MESSAGE);
        }
    } catch (NumberFormatException e) {
        JOptionPane.showConfirmDialog(null, "Please enter numerical values", "Error", JOptionPane.PLAIN_MESSAGE);
    }
    return isValid;


}
private class ButtonListener implements ActionListener { // Inner class
    public void actionPerformed(ActionEvent event) {

        if (validateColor(textRed.getText()) && validateColor(textGreen.getText()) && validateColor(textBlue.getText()))
        {
            Color bgColor = new Color(getColor());
            displayPanel.setBackground(bgColor);    
        }


    }
}
}

回答1:

Your question is about GridLayout but you show code using BorderLayout:

buttonPanel = new JPanel(new BorderLayout());
button = new JButton("Display Color");
button.addActionListener(new ButtonListener ()); // Add event handler
button.setFont(font);
button.setPreferredSize(new Dimension(100, 100));

?

The button always fills up the whole panel, whereas if I remove the gridlayout, the button won't have the same behavior.

This is GridLayout default behavior, it space is divided equally and each component takes up the full space (same would apply for BorderLayout).

There are many other LayoutManagers which will will meet your needs:

  • A Visual Guide to Layout Managers

You may want to look at GridBagLayout which is more flexible:

buttonPanel = new JPanel(new GridBagLayout());
button = new JButton("Display Color");
button.addActionListener(new ButtonListener()); // Add event handler
button.setFont(font);


GridBagConstraints gc=new GridBagConstraints();
gc.fill=GridBagConstraints.HORIZONTAL;
gc.gridx=0;
gc.gridy=0;
            
buttonPanel.add(button,gc);

or even the default JPanel FlowLayout:

    buttonPanel = new JPanel();
    button = new JButton("Display Color");
    button.addActionListener(new ButtonListener()); // Add event handler
    button.setFont(font);

    buttonPanel.add(button);

Or a 3rd party LayoutManger like MigLayout.

Other suggestions:

  • Dont call setPreferredSize(..) rather override getPreferredSize() and even than only do this when painting to the Graphics object or wanting to make a component bigger/smaller dont do this for Layout purposes thats a LayoutManagers job.

  • Also always remember to create and manipulate Swing components on the Event Dispatch Thread via SwingUtilities.invokeLater(Runnable r) block



回答2:

Replace your getButtonPanel() with this method ( I've used GroupLayout to make it work),

public JPanel getButtonPanel(){

    JPanel jPanel1 = new JPanel();
    button = new JButton("Display Color");
    button.addActionListener(new ButtonListener ()); // Add event handler
    button.setFont(font);
    javax.swing.GroupLayout jPanel1Layoutx = new javax.swing.GroupLayout(jPanel1);
                    jPanel1.setLayout(jPanel1Layoutx);
                    jPanel1Layoutx.setHorizontalGroup(
                            jPanel1Layoutx.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(jPanel1Layoutx.createSequentialGroup().addContainerGap().addComponent(button, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
                    jPanel1Layoutx.setVerticalGroup(
                            jPanel1Layoutx.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(jPanel1Layoutx.createSequentialGroup().addComponent(button, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE).addGap(0, 12, Short.MAX_VALUE)));

    return jPanel1;

}

Instead of 24 u can set button size that u prefer !



回答3:

Simply create a JPanel, and add that JPanel to the layout of the frame. Now inside that JPanel, lets call it holderPanel, you add the button. Now the button doesn't take up the entire space! Feel free to do some of the following to better suite your program:

  • holderPanel.setOpaque(false); //So the panel is invisible, but your button is
  • holderPanel.setBorder(new EmptyBorder(80, 50, 20, 130));


回答4:

Try this, it worked for me.

JFrame frame=new JFrame();
JPanel p1 = new JPanel(new GridLayout(2,1));
JLabel lb1= new JLabel("Test1");
JButton button1 = new JButton("Go to whatever");
button1.addActionListener();
JPanel p2=new JPanel();
p2.add(button1);
p1.add(p2);
frame.add(p1);