GridBagLayout 锚点精确性
GridBagLayout anchor preciseness
我可以消除容器周围的随机红线吗?或者这是 JDK 中的错误?
3x3 网格使用 enchor
约束添加了 9 个尺寸较小的组件,但未按预期工作。
重现问题的完整源代码
import static java.awt.Color.red;
import static java.awt.Color.white;
import static java.awt.GridBagConstraints.CENTER;
import static java.awt.GridBagConstraints.FIRST_LINE_END;
import static java.awt.GridBagConstraints.FIRST_LINE_START;
import static java.awt.GridBagConstraints.LAST_LINE_END;
import static java.awt.GridBagConstraints.LAST_LINE_START;
import static java.awt.GridBagConstraints.LINE_END;
import static java.awt.GridBagConstraints.LINE_START;
import static java.awt.GridBagConstraints.PAGE_END;
import static java.awt.GridBagConstraints.PAGE_START;
import static javax.swing.BorderFactory.createLineBorder;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GridBagLayoutTest {
public static void main(String[] args) {
JPanel pane = new JPanel(new GridBagLayout());
pane.setBackground(red);
pane.setPreferredSize(new Dimension(500, 500));
// pane.setBorder(createEmptyBorder());
// pane.setBorder(createLineBorder(white, 1));
pane.setBorder(createLineBorder(white, 2));
// pane.setBorder(createLineBorder(white, 3));
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.weighty = 1;
c.gridx = 0;
c.gridy = 0;
c.anchor = FIRST_LINE_START;
pane.add(rectangle(), c);
c.gridx = 1;
c.gridy = 0;
c.anchor = PAGE_START;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 0;
c.anchor = FIRST_LINE_END;
pane.add(rectangle(), c);
c.gridx = 0;
c.gridy = 1;
c.anchor = LINE_START;
pane.add(rectangle(), c);
c.gridx = 1;
c.gridy = 1;
c.anchor = CENTER;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 1;
c.anchor = LINE_END;
pane.add(rectangle(), c);
c.gridx = 0;
c.gridy = 2;
c.anchor = LAST_LINE_START;
pane.add(rectangle(), c);
c.gridx = 1;
c.gridy = 2;
c.anchor = PAGE_END;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 2;
c.anchor = LAST_LINE_END;
pane.add(rectangle(), c);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 600));
frame.getContentPane().setLayout(new GridBagLayout());
frame.getContentPane().setBackground(white);
frame.getContentPane().add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static JPanel rectangle() {
JPanel rect = new JPanel();
rect.setBackground(white);
rect.setPreferredSize(new Dimension(100, 100));
return rect;
}
}
this is a bug in JDK?
好吧,您正在尝试以一种非设计用途的方式使用 GridBagLayout。您正在尝试在每个 row/column.
中使用 3 个组件制作一个 5 组件网格
每个单元格的大小为 500 / 3 = 166.666。
当您尝试设置每个组件的位置时,您会遇到一些舍入问题。有时向上舍入,有时向下舍入。
要检查这一点,您可以删除 setBorder(...) 语句,然后在 setVisible() 语句之后添加:
for (Component panel: pane.getComponents())
System.out.println(panel.getBounds());
你会看到如下输出:
java.awt.Rectangle[x=1,y=1,width=100,height=100]
java.awt.Rectangle[x=200,y=1,width=100,height=100]
java.awt.Rectangle[x=399,y=1,width=100,height=100]
java.awt.Rectangle[x=1,y=200,width=100,height=100]
java.awt.Rectangle[x=200,y=200,width=100,height=100]
java.awt.Rectangle[x=399,y=200,width=100,height=100]
java.awt.Rectangle[x=1,y=399,width=100,height=100]
java.awt.Rectangle[x=200,y=399,width=100,height=100]
java.awt.Rectangle[x=399,y=399,width=100,height=100]
要解决此问题,您可以创建一个 5x5 网格并将每个组件添加到网格中的适当单元格中:
import static java.awt.Color.red;
import static java.awt.Color.white;
import static java.awt.GridBagConstraints.CENTER;
import static java.awt.GridBagConstraints.FIRST_LINE_END;
import static java.awt.GridBagConstraints.FIRST_LINE_START;
import static java.awt.GridBagConstraints.LAST_LINE_END;
import static java.awt.GridBagConstraints.LAST_LINE_START;
import static java.awt.GridBagConstraints.LINE_END;
import static java.awt.GridBagConstraints.LINE_START;
import static java.awt.GridBagConstraints.PAGE_END;
import static java.awt.GridBagConstraints.PAGE_START;
import static javax.swing.BorderFactory.createLineBorder;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Arrays;
public class GridBagLayoutTest2 {
public static void main(String[] args) {
GridBagLayout gbl = new GridBagLayout();
JPanel pane = new JPanel(gbl);
pane.setBackground(red);
// pane.setPreferredSize(new Dimension(500, 500));
// pane.setBorder(createEmptyBorder());
// pane.setBorder(createLineBorder(white, 1));
pane.setBorder(createLineBorder(white, 2));
// pane.setBorder(createLineBorder(white, 3));
// The minimimum width of a column is 100 pixels
// and the minimum height of a row is 100 pixels.
int[] columns = new int[5];
Arrays.fill(columns, 100);
gbl.columnWidths = columns;
int[] rows = new int[5];
Arrays.fill(rows, 100);
gbl.rowHeights = rows;
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.weighty = 1;
c.gridx = 0;
c.gridy = 0;
// c.anchor = FIRST_LINE_START;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 0;
// c.anchor = PAGE_START;
pane.add(rectangle(), c);
c.gridx = 4;
c.gridy = 0;
// c.anchor = FIRST_LINE_END;
pane.add(rectangle(), c);
c.gridx = 0;
c.gridy = 2;
// c.anchor = LINE_START;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 2;
// c.anchor = CENTER;
pane.add(rectangle(), c);
c.gridx = 4;
c.gridy = 2;
// c.anchor = LINE_END;
pane.add(rectangle(), c);
c.gridx = 0;
c.gridy = 4;
// c.anchor = LAST_LINE_START;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 4;
// c.anchor = PAGE_END;
pane.add(rectangle(), c);
c.gridx = 4;
c.gridy = 4;
// c.anchor = LAST_LINE_END;
pane.add(rectangle(), c);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 600));
frame.getContentPane().setLayout(new GridBagLayout());
frame.getContentPane().setBackground(white);
frame.getContentPane().add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static JPanel rectangle() {
JPanel rect = new JPanel();
rect.setBackground(white);
rect.setPreferredSize(new Dimension(100, 100));
return rect;
}
}
这个有效的原因见:
编辑:
GridLayout 也有同样的问题。如果父面板的 width/height 不能被 GridLayout 中组件的数量整除,那么组件将不会填满整个 space 并且父面板的背景会透出来。
作为对您提供的代码的破解,您可以使用:
Border line = new LineBorder(Color.WHITE);
Border empty = new EmptyBorder(-1, -1, -1, -1);
Border compound = new CompoundBorder(line, empty);
pane.setBorder(compound);
这将允许在不影响组件在面板中的位置的情况下绘制 LineBorder,因为边框插入将保留 (0, 0, 0, 0)。
您还应该能够使用 MatteBorder 并且只绘制底线并相应地调整 EmptyBorder。
我可以消除容器周围的随机红线吗?或者这是 JDK 中的错误?
3x3 网格使用 enchor
约束添加了 9 个尺寸较小的组件,但未按预期工作。
重现问题的完整源代码
import static java.awt.Color.red;
import static java.awt.Color.white;
import static java.awt.GridBagConstraints.CENTER;
import static java.awt.GridBagConstraints.FIRST_LINE_END;
import static java.awt.GridBagConstraints.FIRST_LINE_START;
import static java.awt.GridBagConstraints.LAST_LINE_END;
import static java.awt.GridBagConstraints.LAST_LINE_START;
import static java.awt.GridBagConstraints.LINE_END;
import static java.awt.GridBagConstraints.LINE_START;
import static java.awt.GridBagConstraints.PAGE_END;
import static java.awt.GridBagConstraints.PAGE_START;
import static javax.swing.BorderFactory.createLineBorder;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GridBagLayoutTest {
public static void main(String[] args) {
JPanel pane = new JPanel(new GridBagLayout());
pane.setBackground(red);
pane.setPreferredSize(new Dimension(500, 500));
// pane.setBorder(createEmptyBorder());
// pane.setBorder(createLineBorder(white, 1));
pane.setBorder(createLineBorder(white, 2));
// pane.setBorder(createLineBorder(white, 3));
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.weighty = 1;
c.gridx = 0;
c.gridy = 0;
c.anchor = FIRST_LINE_START;
pane.add(rectangle(), c);
c.gridx = 1;
c.gridy = 0;
c.anchor = PAGE_START;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 0;
c.anchor = FIRST_LINE_END;
pane.add(rectangle(), c);
c.gridx = 0;
c.gridy = 1;
c.anchor = LINE_START;
pane.add(rectangle(), c);
c.gridx = 1;
c.gridy = 1;
c.anchor = CENTER;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 1;
c.anchor = LINE_END;
pane.add(rectangle(), c);
c.gridx = 0;
c.gridy = 2;
c.anchor = LAST_LINE_START;
pane.add(rectangle(), c);
c.gridx = 1;
c.gridy = 2;
c.anchor = PAGE_END;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 2;
c.anchor = LAST_LINE_END;
pane.add(rectangle(), c);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 600));
frame.getContentPane().setLayout(new GridBagLayout());
frame.getContentPane().setBackground(white);
frame.getContentPane().add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static JPanel rectangle() {
JPanel rect = new JPanel();
rect.setBackground(white);
rect.setPreferredSize(new Dimension(100, 100));
return rect;
}
}
this is a bug in JDK?
好吧,您正在尝试以一种非设计用途的方式使用 GridBagLayout。您正在尝试在每个 row/column.
中使用 3 个组件制作一个 5 组件网格每个单元格的大小为 500 / 3 = 166.666。
当您尝试设置每个组件的位置时,您会遇到一些舍入问题。有时向上舍入,有时向下舍入。
要检查这一点,您可以删除 setBorder(...) 语句,然后在 setVisible() 语句之后添加:
for (Component panel: pane.getComponents())
System.out.println(panel.getBounds());
你会看到如下输出:
java.awt.Rectangle[x=1,y=1,width=100,height=100]
java.awt.Rectangle[x=200,y=1,width=100,height=100]
java.awt.Rectangle[x=399,y=1,width=100,height=100]
java.awt.Rectangle[x=1,y=200,width=100,height=100]
java.awt.Rectangle[x=200,y=200,width=100,height=100]
java.awt.Rectangle[x=399,y=200,width=100,height=100]
java.awt.Rectangle[x=1,y=399,width=100,height=100]
java.awt.Rectangle[x=200,y=399,width=100,height=100]
java.awt.Rectangle[x=399,y=399,width=100,height=100]
要解决此问题,您可以创建一个 5x5 网格并将每个组件添加到网格中的适当单元格中:
import static java.awt.Color.red;
import static java.awt.Color.white;
import static java.awt.GridBagConstraints.CENTER;
import static java.awt.GridBagConstraints.FIRST_LINE_END;
import static java.awt.GridBagConstraints.FIRST_LINE_START;
import static java.awt.GridBagConstraints.LAST_LINE_END;
import static java.awt.GridBagConstraints.LAST_LINE_START;
import static java.awt.GridBagConstraints.LINE_END;
import static java.awt.GridBagConstraints.LINE_START;
import static java.awt.GridBagConstraints.PAGE_END;
import static java.awt.GridBagConstraints.PAGE_START;
import static javax.swing.BorderFactory.createLineBorder;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.util.Arrays;
public class GridBagLayoutTest2 {
public static void main(String[] args) {
GridBagLayout gbl = new GridBagLayout();
JPanel pane = new JPanel(gbl);
pane.setBackground(red);
// pane.setPreferredSize(new Dimension(500, 500));
// pane.setBorder(createEmptyBorder());
// pane.setBorder(createLineBorder(white, 1));
pane.setBorder(createLineBorder(white, 2));
// pane.setBorder(createLineBorder(white, 3));
// The minimimum width of a column is 100 pixels
// and the minimum height of a row is 100 pixels.
int[] columns = new int[5];
Arrays.fill(columns, 100);
gbl.columnWidths = columns;
int[] rows = new int[5];
Arrays.fill(rows, 100);
gbl.rowHeights = rows;
GridBagConstraints c = new GridBagConstraints();
c.weightx = 1;
c.weighty = 1;
c.gridx = 0;
c.gridy = 0;
// c.anchor = FIRST_LINE_START;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 0;
// c.anchor = PAGE_START;
pane.add(rectangle(), c);
c.gridx = 4;
c.gridy = 0;
// c.anchor = FIRST_LINE_END;
pane.add(rectangle(), c);
c.gridx = 0;
c.gridy = 2;
// c.anchor = LINE_START;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 2;
// c.anchor = CENTER;
pane.add(rectangle(), c);
c.gridx = 4;
c.gridy = 2;
// c.anchor = LINE_END;
pane.add(rectangle(), c);
c.gridx = 0;
c.gridy = 4;
// c.anchor = LAST_LINE_START;
pane.add(rectangle(), c);
c.gridx = 2;
c.gridy = 4;
// c.anchor = PAGE_END;
pane.add(rectangle(), c);
c.gridx = 4;
c.gridy = 4;
// c.anchor = LAST_LINE_END;
pane.add(rectangle(), c);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 600));
frame.getContentPane().setLayout(new GridBagLayout());
frame.getContentPane().setBackground(white);
frame.getContentPane().add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static JPanel rectangle() {
JPanel rect = new JPanel();
rect.setBackground(white);
rect.setPreferredSize(new Dimension(100, 100));
return rect;
}
}
这个有效的原因见:
编辑:
GridLayout 也有同样的问题。如果父面板的 width/height 不能被 GridLayout 中组件的数量整除,那么组件将不会填满整个 space 并且父面板的背景会透出来。
作为对您提供的代码的破解,您可以使用:
Border line = new LineBorder(Color.WHITE);
Border empty = new EmptyBorder(-1, -1, -1, -1);
Border compound = new CompoundBorder(line, empty);
pane.setBorder(compound);
这将允许在不影响组件在面板中的位置的情况下绘制 LineBorder,因为边框插入将保留 (0, 0, 0, 0)。
您还应该能够使用 MatteBorder 并且只绘制底线并相应地调整 EmptyBorder。