问题
I am trying to create the following GUI:
but the GUI that I make is:
What my grid looks like:
image: THE GRIDLAYOUT FOR THIS
I don't understand why I am getting this output since I have drawn a diagram to aid the code and it seems to work out.
The method addComp adds adds the input component to the input panel at a given (x, y) position and at a given component width and height.
Code:
import javax.swing.*;
import java.awt.*;
public class GUIError extends JFrame {
//initialise all the components
JPanel mainPanel = new JPanel();
JTextField txtDisplay = new JTextField();
JButton btnA = new JButton("A");
JButton btnB = new JButton("B");
JButton btnC = new JButton("C");
JButton btnD = new JButton("D");
JButton btnE = new JButton("E");
JButton btnF = new JButton("F");
JButton btnWA = new JButton("WA");
JButton btnWB = new JButton("WB");
JButton btnWC = new JButton("WC");
JButton btnWD = new JButton("WD");
private void addComp(JPanel panel, JComponent comp, int xPos, int yPos, int compWidth, int compHeight) {
GridBagConstraints gridConstraints = new GridBagConstraints();
gridConstraints.gridx = xPos;
gridConstraints.gridy = yPos;
gridConstraints.gridwidth = compWidth;
gridConstraints.gridheight = compHeight;
gridConstraints.weightx = 0.5;
gridConstraints.weighty = 0.5;
gridConstraints.insets = new Insets(5, 5, 5, 5);
gridConstraints.anchor = GridBagConstraints.CENTER;
gridConstraints.fill = GridBagConstraints.BOTH;
panel.add(comp, gridConstraints);
}
public static void main(String[] args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
}
catch (Exception e) { }
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// create frame
JFrame frame = new JFrame("Calculator");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setLocationRelativeTo(null);
Container c = frame.getContentPane();
// create GUI within frame
new GUIError(c);
// finish frame definition
frame.pack();
frame.setResizable(false);
frame.setVisible(true);
}
});
}
public GUIError(Container cont) {
cont.setPreferredSize(new Dimension(610, 250));
// parent panel containes every other panel
mainPanel.setLayout(new GridBagLayout());
// text display
txtDisplay.setEditable(false);
addComp(mainPanel, txtDisplay, 0, 0, 12, 2); // width 16, height 2
addComp(mainPanel, btnA, 0, 2, 2, 1);
addComp(mainPanel, btnB, 2, 2, 2, 1);
addComp(mainPanel, btnC, 4, 2, 2, 1);
addComp(mainPanel, btnD, 6, 2, 2, 1);
addComp(mainPanel, btnE, 8, 2, 2, 1);
addComp(mainPanel, btnF, 10, 2, 2, 1);
addComp(mainPanel, btnWA, 0, 3, 3, 1);
addComp(mainPanel, btnWB, 3, 3, 3, 1);
addComp(mainPanel, btnWC, 6, 3, 3, 1);
addComp(mainPanel, btnWD, 9, 3, 3, 1);
cont.add(mainPanel);
}
}
回答1:
It can easily be achieved by using GridBagLayout
as seen in this example presented below. You simply need to take two JPanel
one each for each ROW. Both using GridBagLayout
, and add components to the first row, with weightx = 0.16 since each JButton
is suppose to take this much area, and for the second row weightx = 0.25 since, this is the area occupied by each JButton
along the X direction
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridBagExample {
private static final int SIZE = 10;
private JButton[] buttons;
private GridBagConstraints gbc;
public GridBagExample() {
buttons = new JButton[SIZE];
gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
}
private void createAndDisplayGUI() {
JFrame frame = new JFrame("Grid Game");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridLayout(2, 1, 5, 5));
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel topPanel = new JPanel();
JTextField textField = new JTextField(10);
//topPanel.add(textField);
JPanel buttonPanel = new JPanel(new GridLayout(2, 1, 5, 5));
JPanel headerPanel = new JPanel(new GridBagLayout());
buttons[0] = new JButton("A");
addComp(headerPanel, buttons[0], 0, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
buttons[1] = new JButton("B");
addComp(headerPanel, buttons[1], 1, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
buttons[2] = new JButton("C");
addComp(headerPanel, buttons[2], 2, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
buttons[3] = new JButton("D");
addComp(headerPanel, buttons[3], 3, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
buttons[4] = new JButton("E");
addComp(headerPanel, buttons[4], 4, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
buttons[5] = new JButton("F");
addComp(headerPanel, buttons[5], 5, 0, 0.16, 1.0, 1, 1, GridBagConstraints.BOTH);
JPanel footerPanel = new JPanel(new GridBagLayout());
buttons[6] = new JButton("WA");
addComp(footerPanel, buttons[6], 0, 0, 0.25, 1.0, 1, 1, GridBagConstraints.BOTH);
buttons[7] = new JButton("WB");
addComp(footerPanel, buttons[7], 1, 0, 0.25, 1.0, 1, 1, GridBagConstraints.BOTH);
buttons[8] = new JButton("WC");
addComp(footerPanel, buttons[8], 2, 0, 0.25, 1.0, 1, 1, GridBagConstraints.BOTH);
buttons[9] = new JButton("WD");
addComp(footerPanel, buttons[9], 3, 0, 0.25, 1.0, 1, 1, GridBagConstraints.BOTH);
buttonPanel.add(headerPanel);
buttonPanel.add(footerPanel);
contentPane.add(textField);
contentPane.add(buttonPanel);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private void addComp(JPanel panel, JComponent comp, int x, int y,
double wx, double wy, int gw, int gh, int fill) {
gbc.gridx = x;
gbc.gridy = y;
gbc.weightx = wx;
gbc.weighty = wy;
gbc.gridwidth = gw;
gbc.gridheight = gh;
gbc.fill = fill;
panel.add(comp, gbc);
}
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GridBagExample().createAndDisplayGUI();
}
});
}
}
OUTPUT: GRIDBAGLAYOUT:
The same output can be achieved by GridLayout
, if GridBagLayout
is not a necessity in this case, as cited in the below example:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GridBagExample {
private static final int SIZE = 10;
private JButton[] buttons;
public GridBagExample() {
buttons = new JButton[SIZE];
}
private void createAndDisplayGUI() {
JFrame frame = new JFrame("Grid Game");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
contentPane.setLayout(new GridLayout(2, 1, 5, 5));
contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel topPanel = new JPanel();
JTextArea tArea = new JTextArea(5, 30);
JScrollPane scroller = new JScrollPane();
scroller.setViewportView(tArea);
topPanel.add(scroller);
JPanel buttonPanel = new JPanel(new GridLayout(2, 1, 5, 5));
JPanel headerPanel = new JPanel(new GridLayout(1, 0, 5, 5));
buttons[0] = new JButton("A");
headerPanel.add(buttons[0]);
buttons[1] = new JButton("B");
headerPanel.add(buttons[1]);
buttons[2] = new JButton("C");
headerPanel.add(buttons[2]);
buttons[3] = new JButton("D");
headerPanel.add(buttons[3]);
buttons[4] = new JButton("E");
headerPanel.add(buttons[4]);
buttons[5] = new JButton("F");
headerPanel.add(buttons[5]);
JPanel footerPanel = new JPanel(new GridLayout(1, 0, 5, 5));
buttons[6] = new JButton("WA");
footerPanel.add(buttons[6]);
buttons[7] = new JButton("WB");
footerPanel.add(buttons[7]);
buttons[8] = new JButton("WC");
footerPanel.add(buttons[8]);
buttons[9] = new JButton("WD");
footerPanel.add(buttons[9]);
buttonPanel.add(headerPanel);
buttonPanel.add(footerPanel);
contentPane.add(topPanel);
contentPane.add(buttonPanel);
frame.setContentPane(contentPane);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new GridBagExample().createAndDisplayGUI();
}
});
}
}
OUTPUT: GRIDLAYOUT:
回答2:
Normally I'd make separate panels, but hey, who doesn't like a challenge?
The problem is that some of the columns are not well-defined for GBL (there's no single component defining its width), so button WA doesn't know how far out to go to cover half of button B, etc.
So, I added some zero-width spacers in the columns that make up the needed sections.
All in one panel:
import java.awt.*;
import javax.swing.*;
public class GridBagDemo3 implements Runnable
{
private JPanel panel;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new GridBagDemo3());
}
public void run()
{
JTextArea text = new JTextArea(10,10);
JButton btnA = new JButton("A");
JButton btnB = new JButton("B");
JButton btnC = new JButton("C");
JButton btnD = new JButton("D");
JButton btnE = new JButton("E");
JButton btnF = new JButton("F");
JButton btnWA = new JButton("WA");
JButton btnWB = new JButton("WB");
JButton btnWC = new JButton("WC");
JButton btnWD = new JButton("WD");
panel = new JPanel(new GridBagLayout());
add(text, 0,0, 12,1);
add(btnA, 0,1, 2,1);
add(btnB, 2,1, 2,1);
add(btnC, 4,1, 2,1);
add(btnD, 6,1, 2,1);
add(btnE, 8,1, 2,1);
add(btnF, 10,1, 2,1);
add(btnWA, 0,2, 3,1);
add(btnWB, 3,2, 3,1);
add(btnWC, 6,2, 3,1);
add(btnWD, 9,2, 3,1);
// SPACERS: define the 2 columns that button B spans
// so that WA and WB can split B, and same for button E
add(null, 2,2, 1,1);
add(null, 3,2, 1,1);
add(null, 8,2, 1,1);
add(null, 9,2, 1,1);
JFrame frame = new JFrame("Grig Bag");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
}
private void add(Component comp, int x, int y, int colspan, int rowspan)
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = colspan;
gbc.gridheight = rowspan;
gbc.weighty = .1;
gbc.anchor = GridBagConstraints.CENTER;
gbc.fill = GridBagConstraints.BOTH;
gbc.insets = new Insets(5,5,5,5);
if (comp != null)
{
gbc.weightx = 1;
}
else
{
comp = Box.createHorizontalGlue();
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.1;
gbc.weighty = 0;
}
panel.add(comp, gbc);
}
}
回答3:
@Matthieu wrote -
could you elaborate on GBC are column based? It sounds like an explanation of a problem I noticed...
I think that this way is GridBagLayout designed, I'm always using the JLabels (without the Borders:-) as an matrix ...
import java.awt.*;
import javax.swing.*;
public class CopyTextNorthPanel extends JPanel {
private static final long serialVersionUID = 1L;
private JLabel hidelLabel;
private JLabel firstLabel;
private JTextField firstText;
public CopyTextNorthPanel() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
for (int k = 0; k < 50; k++) {
hidelLabel = new JLabel(" ");
hidelLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 0.5;
gbc.weighty = 0.5;
gbc.gridx = k;
gbc.gridy = 0;
add(hidelLabel, gbc);
}
for (int k = 0; k < 5; k++) {
firstLabel = new JLabel("Testing Label : ", SwingConstants.RIGHT);
firstLabel.setFont(new Font("Serif", Font.BOLD, 20));
firstLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 0, 5, 0);
gbc.gridx = 0;
gbc.gridwidth = 8;
gbc.gridy = k + 1;
add(firstLabel, gbc);
}
for (int k = 0; k < 5; k++) {
firstText = new JTextField("Testing TextField");
firstText.setFont(new Font("Serif", Font.BOLD, 20));
firstText.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 0, 5, 0);
gbc.gridx = 9;
gbc.gridwidth = k + 8;
gbc.gridy = k + 1;
add(firstText, gbc);
}
for (int k = 0; k < 5; k++) {
firstLabel = new JLabel("Testing Label : ", SwingConstants.RIGHT);
firstLabel.setFont(new Font("Serif", Font.BOLD, 20));
firstLabel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 0, 5, 0);
gbc.gridx = 20 + k;
gbc.gridwidth = 8;
gbc.gridy = k + 1;
add(firstLabel, gbc);
}
for (int k = 0; k < 5; k++) {
firstText = new JTextField("Testing TextField");
firstText.setFont(new Font("Serif", Font.BOLD, 20));
firstText.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(0, 0, 5, 0);
gbc.gridx = 29 + k;
gbc.gridwidth = 21 - k;
gbc.gridy = k + 1;
add(firstText, gbc);
}
}
}
回答4:
if you are still interested to understand your error: grid' layout isn't FlowLayout, you can't simply add component and it gonna draw object the same moment program reads it. In case of grid, virtual machine first read all objects and than build grid, the amount of columns is determined in base of those rows which has biggest number of columns. So, you had good idea to prefer 12 columns (thus you avoid creation of new "Panel" and spare system resources), but to do it right you simply should have add 12 empty spaces(not just empty but also with zero size) in one of the rows
// text display
txtDisplay.setEditable(false);
addComp(mainPanel, txtDisplay, 0, 0, 12, 2); // width 16, height 2
//now go with empty spaces
for(int i=0;i<12;i++){
GridBagConstraints gridConstraints = new GridBagConstraints();
gridConstraints.gridx = i; //12 times "i"
gridConstraints.gridy = 1; //you left y=1 empty, so why don't use it
gridConstraints.gridwidth = 1; //one column = one space in grid
gridConstraints.gridheight = 0; //we don't want it to occupied any space
gridConstraints.weightx = 0.5;
gridConstraints.weighty = 0.5;
gridConstraints.insets = new Insets(0, 0, 0, 0); //same reason, we don't want it to occupied any space
gridConstraints.anchor = GridBagConstraints.CENTER;
gridConstraints.fill = GridBagConstraints.BOTH ;
mainPanel.add(Box.createHorizontalGlue(), gridConstraints);
}
addComp(mainPanel, btnA, 0, 2, 2, 1);
addComp(mainPanel, btnB, 2, 2, 2, 1);
addComp(mainPanel, btnC, 4, 2, 2, 1);
addComp(mainPanel, btnD, 6, 2, 2, 1);
addComp(mainPanel, btnE, 8, 2, 2, 1);
addComp(mainPanel, btnF, 10, 2, 2, 1);
addComp(mainPanel, btnWA, 0, 3, 3, 1);
addComp(mainPanel, btnWB, 3, 3, 3, 1);
addComp(mainPanel, btnWC, 6, 3, 3, 1);
addComp(mainPanel, btnWD, 9, 3, 3, 1);
来源:https://stackoverflow.com/questions/24291030/gridbaglayout-gridding-not-working