You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java GUI记忆游戏:JFrame与组件自适应布局问题求助

问题:Java GUI记忆游戏布局适配异常
  • 已完成Java GUI记忆游戏核心功能,但布局适配存在问题:键盘、随难度变化的网格(简单3×4/中等4×7/困难7×8)、左侧TurnBox组件无法适配JFrame,界面布局混乱
  • 尝试过的无效方案:设置大尺寸JFrame后调用pack();移除width参数改用固定值能对齐网格,但会导致TurnBox消失

提供的代码片段

TurnBox构造代码

public TurnBox(MemoryFrame view, MemoryModel model, int width) //extends JPanel
{
    this.model = model;
    this.letterWidth = 64;
    this.insets = new Insets(0, 6, 6, 6); 
    this.topMargin = 0;
    int wordWidth = (letterWidth + insets.right) * model.getColumns(); //# of columns in the game
    this.leftMargin = (width - wordWidth)/2;
    int height = (letterWidth + insets.bottom) * model.getRows() //# of rows in the game
            + 2 * topMargin;
    this.setPreferredSize(new Dimension(width, height));
    this.turn = buildRectangle();
}


private Rectangle buildRectangle()
{
    
    int x = 50;
    int y = topMargin;
    
    Rectangle turn = new Rectangle(x, y, letterWidth,
            letterWidth);
    
    return turn;
}

MemoryBoard构造代码

public MemoryBoard(MemoryFrame view, MemoryModel model, int width)
{
    this.model = model;
    this.action = new KeyBoardButtonAction(view, model);
    this.topMargin = 0;
    this.letterWidth = 64;
    this.insets = new Insets(0, 6, 6, 6); //Distance between squares

    int wordWidth = (letterWidth + insets.right) * model.getColumns();
    this.leftMargin = (width - wordWidth) / 2;
    int height = (letterWidth + insets.bottom) * model.getRows()
            + 2 * topMargin;
    this.setPreferredSize(new Dimension(width, height));
    this.grid = buildGrid();
}

private Rectangle[][] buildGrid() { //Part 3 here, change size of grid
    Rectangle[][] grid = new Rectangle[model.getRows()][model.getColumns()];
    //Rectangle[][] grid = new Rectangle[7][6];

    int x = leftMargin;
    int y = topMargin;

    for (int row = 0; row < model.getRows(); row++) {
        for (int column = 0; column < model.getColumns(); column++) {
            grid[row][column] = new Rectangle(x, y, letterWidth,
                    letterWidth);
            x += letterWidth + insets.right;
        }
        x = leftMargin;
        y += letterWidth + insets.bottom;
    }

    return grid;
}

MemoryFrame构造代码

public MemoryFrame(MemoryModel model, StartingFrame s)
{
    this.model = model;
    this.start = s;
    this.keyboardPanel = new KeyboardPanel(this, model);
    int width = keyboardPanel.getPanel().getPreferredSize().width;
    this.board = new MemoryBoard(this, model, width);
    this.turn = new TurnBox(this, model, width);
    
    this.frame = initializeFrame();
}

private JFrame initializeFrame()
{
    
    JFrame frame = new JFrame("GUI Memory Game");
    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    //frame.setJMenuBar(createMenuBar());
    frame.setResizable(false);
    //frame.setSize(1000,1000);
    frame.addWindowListener(new WindowAdapter() {
        @Override
         public void windowClosing(WindowEvent event) {
            shutdown();
        }
    });
    
    frame.add(createTitlePanel(), BorderLayout.NORTH);
    frame.add(turn, BorderLayout.WEST);
    frame.add(board, BorderLayout.CENTER); //Change according to difficulty
    frame.add(keyboardPanel.getPanel(), BorderLayout.SOUTH);
    
    frame.pack();
    frame.setLocationByPlatform(true);
    frame.setVisible(true);
    
    System.out.println("Frame size: " + frame.getSize());
    
    return frame;
    
}

解决方案

1. 修复TurnBox的尺寸逻辑

TurnBox当前错误地将键盘面板宽度设为自身PreferredWidth,导致和MemoryBoard宽度冲突,挤占WEST区域空间。修改为固定宽度,高度与网格保持一致:

// 修改TurnBox构造方法
public TurnBox(MemoryFrame view, MemoryModel model) // 移除width参数
{
    this.model = model;
    this.letterWidth = 64;
    this.insets = new Insets(0, 6, 6, 6); 
    this.topMargin = 0;
    // 设置TurnBox固定宽度(单个格子宽度+边距)
    int turnBoxWidth = letterWidth + 20;
    // 高度与MemoryBoard对齐
    int height = (letterWidth + insets.bottom) * model.getRows() + 2 * topMargin;
    this.setPreferredSize(new Dimension(turnBoxWidth, height));
    this.turn = buildRectangle();
}

2. 调整MemoryBoard的宽度计算

MemoryBoard无需依赖键盘宽度,直接根据网格尺寸计算自身宽度,同时取消内部左偏移,让BorderLayout自动居中:

// 修改MemoryBoard构造方法
public MemoryBoard(MemoryFrame view, MemoryModel model) // 移除width参数
{
    this.model = model;
    this.action = new KeyBoardButtonAction(view, model);
    this.topMargin = 0;
    this.letterWidth = 64;
    this.insets = new Insets(0, 6, 6, 6);

    int wordWidth = (letterWidth + insets.right) * model.getColumns();
    this.leftMargin = 0; // 取消左偏移,由布局管理器处理居中
    int height = (letterWidth + insets.bottom) * model.getRows() + 2 * topMargin;
    this.setPreferredSize(new Dimension(wordWidth, height));
    this.grid = buildGrid();
}

// 同步修改buildGrid的起始坐标
private Rectangle[][] buildGrid() {
    Rectangle[][] grid = new Rectangle[model.getRows()][model.getColumns()];

    int x = 0; // 从0开始绘制
    int y = topMargin;

    for (int row = 0; row < model.getRows(); row++) {
        for (int column = 0; column < model.getColumns(); column++) {
            grid[row][column] = new Rectangle(x, y, letterWidth, letterWidth);
            x += letterWidth + insets.right;
        }
        x = 0;
        y += letterWidth + insets.bottom;
    }

    return grid;
}

3. 更新MemoryFrame的组件初始化

移除基于键盘宽度的参数传递,直接初始化组件:

// 修改MemoryFrame构造方法
public MemoryFrame(MemoryModel model, StartingFrame s)
{
    this.model = model;
    this.start = s;
    this.keyboardPanel = new KeyboardPanel(this, model);
    // 不再传递width参数
    this.board = new MemoryBoard(this, model);
    this.turn = new TurnBox(this, model);
    
    this.frame = initializeFrame();
}

4. 优化窗口布局兼容性

  • 确保createTitlePanel()的PreferredHeight合理,避免挤压下方组件
  • 若保留frame.setResizable(false),需确保所有组件的PreferredSize计算准确,让pack()能正确推导窗口尺寸

内容的提问来源于stack exchange,提问作者Derek Kwon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:00:26