dea*_*eau 2 java layout user-interface
我正在制作一个GUI组件来代表窗口中的棋盘.通常它将是一个8x8正方形的网格,虽然有些变体需要10x8板等.第一步是制作一个包含8x8组件网格的面板.
该类Board扩展JPanel并使用a GridLayout来模拟8x8组件的网格.为了完成某些事情,这些只是Square扩展的类JButton.麻烦的是他们不是正方形!
在Board已添加到新鲜实例化JFrame,包装和呈现在屏幕上.当然,现在电路板在用户调整大小时占用整个帧.网格与板一起缩放,这将方块扭曲成矩形.
这并非完全不受欢迎的行为.我希望电路板能够与框架一起扩展.但是,我想确保方块始终保持正方形.电路板可以是矩形(10x8),但应保持固定比例.
我如何获得正方形?
您可以选择使用LayoutManager符合单元格首选大小的代码. GridLayout将为每个单元格提供相等数量的可用空间,这似乎不是您想要的.
例如,像 GridBagLayout

public class TestChessBoard {
public static void main(String[] args) {
new TestChessBoard();
}
public TestChessBoard() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new ChessBoardPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ChessBoardPane extends JPanel {
public ChessBoardPane() {
int index = 0;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Color color = index % 2 == 0 ? Color.BLACK : Color.WHITE;
gbc.gridx = col;
gbc.gridy = row;
add(new Cell(color), gbc);
index++;
}
index++;
}
}
}
public class Cell extends JButton {
public Cell(Color background) {
setContentAreaFilled(false);
setBorderPainted(false);
setBackground(background);
setOpaque(true);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(25, 25);
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新了比例示例
现在,如果你想做一个比例布局(这样无论可用空间如何,网格的每个单元格都保持与另一个单元格成比例),事情开始变得......有趣......

public class TestChessBoard {
public static void main(String[] args) {
new TestChessBoard();
}
public TestChessBoard() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestChessBoard.ChessBoardPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ChessBoardPane extends JPanel {
public ChessBoardPane() {
int index = 0;
setLayout(new ChessBoardLayoutManager());
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
Color color = index % 2 == 0 ? Color.BLACK : Color.WHITE;
add(new TestChessBoard.Cell(color), new Point(col, row));
index++;
}
index++;
}
}
}
public class Cell extends JButton {
public Cell(Color background) {
setContentAreaFilled(false);
setBorderPainted(false);
setBackground(background);
setOpaque(true);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(25, 25);
}
}
public class ChessBoardLayoutManager implements LayoutManager2 {
private Map<Point, Component> mapComps;
public ChessBoardLayoutManager() {
mapComps = new HashMap<>(25);
}
@Override
public void addLayoutComponent(Component comp, Object constraints) {
if (constraints instanceof Point) {
mapComps.put((Point) constraints, comp);
} else {
throw new IllegalArgumentException("ChessBoard constraints must be a Point");
}
}
@Override
public Dimension maximumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
@Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
@Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
@Override
public void invalidateLayout(Container target) {
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
Point[] keys = mapComps.keySet().toArray(new Point[mapComps.size()]);
for (Point p : keys) {
if (mapComps.get(p).equals(comp)) {
mapComps.remove(p);
break;
}
}
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return new CellGrid(mapComps).getPreferredSize();
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
@Override
public void layoutContainer(Container parent) {
int width = parent.getWidth();
int height = parent.getHeight();
int gridSize = Math.min(width, height);
CellGrid grid = new CellGrid(mapComps);
int rowCount = grid.getRowCount();
int columnCount = grid.getColumnCount();
int cellSize = gridSize / Math.max(rowCount, columnCount);
int xOffset = (width - (cellSize * columnCount)) / 2;
int yOffset = (height - (cellSize * rowCount)) / 2;
Map<Integer, List<CellGrid.Cell>> cellRows = grid.getCellRows();
for (Integer row : cellRows.keySet()) {
List<CellGrid.Cell> rows = cellRows.get(row);
for (CellGrid.Cell cell : rows) {
Point p = cell.getPoint();
Component comp = cell.getComponent();
int x = xOffset + (p.x * cellSize);
int y = yOffset + (p.y * cellSize);
comp.setLocation(x, y);
comp.setSize(cellSize, cellSize);
}
}
}
public class CellGrid {
private Dimension prefSize;
private int cellWidth;
private int cellHeight;
private Map<Integer, List<Cell>> mapRows;
private Map<Integer, List<Cell>> mapCols;
public CellGrid(Map<Point, Component> mapComps) {
mapRows = new HashMap<>(25);
mapCols = new HashMap<>(25);
for (Point p : mapComps.keySet()) {
int row = p.y;
int col = p.x;
List<Cell> rows = mapRows.get(row);
List<Cell> cols = mapCols.get(col);
if (rows == null) {
rows = new ArrayList<>(25);
mapRows.put(row, rows);
}
if (cols == null) {
cols = new ArrayList<>(25);
mapCols.put(col, cols);
}
Cell cell = new Cell(p, mapComps.get(p));
rows.add(cell);
cols.add(cell);
}
int rowCount = mapRows.size();
int colCount = mapCols.size();
cellWidth = 0;
cellHeight = 0;
for (List<Cell> comps : mapRows.values()) {
for (Cell cell : comps) {
Component comp = cell.getComponent();
cellWidth = Math.max(cellWidth, comp.getPreferredSize().width);
cellHeight = Math.max(cellHeight, comp.getPreferredSize().height);
}
}
int cellSize = Math.max(cellHeight, cellWidth);
prefSize = new Dimension(cellSize * colCount, cellSize * rowCount);
System.out.println(prefSize);
}
public int getRowCount() {
return getCellRows().size();
}
public int getColumnCount() {
return getCellColumns().size();
}
public Map<Integer, List<Cell>> getCellColumns() {
return mapCols;
}
public Map<Integer, List<Cell>> getCellRows() {
return mapRows;
}
public Dimension getPreferredSize() {
return prefSize;
}
public int getCellHeight() {
return cellHeight;
}
public int getCellWidth() {
return cellWidth;
}
public class Cell {
private Point point;
private Component component;
public Cell(Point p, Component comp) {
this.point = p;
this.component = comp;
}
public Point getPoint() {
return point;
}
public Component getComponent() {
return component;
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)