I have this vexing source written to demonstrate a layout for a game screen mentioned on another question. It puts buttons (or labels, choosable at start-up) into a GridBagLayout
.
If you choose to not use buttons when prompted (before the GUI appears) the entire GUI is nice and compact with no gaps. But if you choose to use buttons it will (if your set up is like mine) look something like this..
Note the red horizontal lines. That is the BG color of the panel showing through. Those lines are not seen when the GUI uses labels. Stretch the GUI a bit to see that it is not even putting a red line after every row (there are nine rows) - though each row uses buttons (the same components).
How to remove the extra vertical space when using buttons?
I figure it must be something I'm forgetting to do when configuring the buttons or the row weights, but I cannot figure out what!
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import java.net.URL;
import javax.imageio.ImageIO;
public class SoccerField {
private JPanel ui = null;
int[] x = {0, 35, 70, 107, 142, 177, 212, 247, 282, 315};
int[] y = {0, 45, 85, 140, 180, 225, 265, 280, 320, 345};
boolean buttons;
SoccerField() {
initUI();
}
public void initUI() {
int result = JOptionPane.showConfirmDialog(ui, "Use buttons?");
buttons = result == JOptionPane.OK_OPTION;
if (ui != null) {
return;
}
ui = new JPanel(new GridBagLayout());
ui.setBackground(Color.RED);
try {
URL url = new URL("http://i.stack.imgur.com/9E5ky.jpg");
BufferedImage img = ImageIO.read(url);
BufferedImage field = img.getSubimage(100, 350, 315, 345);
BufferedImage[] bi = subSampleImageColumns(field);
BufferedImage[][] fieldParts = new BufferedImage[bi.length][];
for (int ii=0; ii<bi.length; ii++) {
fieldParts[ii] = subSampleImageRows(bi[ii]);
}
for (int ii=0; ii<fieldParts[0].length; ii++) {
for (int jj=0; jj<fieldParts.length; jj++) {
addImageToPanel(ui, fieldParts[ii][jj], ii, jj);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void addImageToPanel(JPanel panel, BufferedImage img, int row, int col) {
Insets insets = new Insets(0,0,0,0);
GridBagConstraints gbc = new GridBagConstraints(
row, col,
1, 1,
.5, .5,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
insets, 0, 0);
ImageIcon ii = new ImageIcon(img);
JButton b = new JButton(ii);
b.setBorder(null);
b.setBorderPainted(false);
b.setContentAreaFilled(false);
Component c = buttons ? b : new JLabel(ii);
panel.add(c, gbc);
}
private BufferedImage[] subSampleImageColumns(BufferedImage img) {
System.out.println("Image Size: " + img.getWidth() + "," + img.getHeight());
BufferedImage[] imageRows = new BufferedImage[x.length - 1];
for (int ii = 0; ii < x.length - 1; ii++) {
BufferedImage bi = img.getSubimage(
x[ii], 0, x[ii + 1] - x[ii], img.getHeight());
imageRows[ii] = bi;
}
return imageRows;
}
private BufferedImage[] subSampleImageRows(BufferedImage img) {
BufferedImage[] imageRows = new BufferedImage[y.length - 1];
for (int ii = 0; ii < y.length - 1; ii++) {
BufferedImage bi = img.getSubimage(
0, y[ii], img.getWidth(), y[ii + 1] - y[ii]);
imageRows[ii] = bi;
}
return imageRows;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
SoccerField o = new SoccerField();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
//f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
Noticed that the preferred height of the buttons doesn't seem to be calculated correctly for the buttons (in some cases).
In the cases where the height of the label is 40, the height of the button was 41.
Its like the button will always resize to an odd number?
I changed the code:
//int[] y = {0, 45, 85, 140, 180, 225, 265, 280, 320, 345};
int[] y = {0, 45, 86, 139, 180, 225, 266, 279, 320, 345};
and it seems to work.
Ah, just found the reason. You also need:
b.setFocusPainted(false);
来源:https://stackoverflow.com/questions/32540954/removing-space-around-buttons-in-gridbaglayout