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

如何使用Java Swing创建圆形JButton实现9x9围棋棋盘落子功能

实现思路

1. 自定义圆形棋子按钮

需要单独创建StoneButton类继承JButton,重写绘制逻辑实现圆形效果,同时屏蔽默认按钮的样式干扰:

  • 重写paintComponent方法绘制固定65*65尺寸的填充圆
  • 去掉默认的按钮边框、内容填充、焦点绘制,避免方形背景外露
  • 重写contains方法保证点击区域仅响应圆形范围

2. JPanel整合与棋子定位

你的Board类本身就是JPanel的子类,直接在Board上做布局即可:

  • 给Board设置绝对定位布局(setLayout(null)),所有棋子按钮直接添加到Board实例上,不要添加到外层JFrame
  • 棋子放置坐标需要和你绘制网格的计算逻辑对齐:你当前网格的交叉点坐标为x=10 + i*(getWidth()-20)/9、y=10 + j*(getHeight()-20)/9,将按钮的左上角坐标设为交叉点x - 32、交叉点y -32(32是65*65按钮的半长),即可让按钮中心刚好落在交叉点上。

实现代码

自定义圆形按钮类 StoneButton.java

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;

public class StoneButton extends JButton {
    private Color stoneColor;
    private static final int SIZE = 65;

    public StoneButton(Color color) {
        this.stoneColor = color;
        setPreferredSize(new Dimension(SIZE, SIZE));
        setContentAreaFilled(false); // 取消默认背景填充
        setBorderPainted(false); // 取消默认边框
        setFocusPainted(false); // 取消焦点边框
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        // 抗锯齿优化
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(stoneColor);
        g2d.fillOval(0, 0, SIZE, SIZE);
        g2d.dispose();
    }

    @Override
    public boolean contains(int x, int y) {
        // 限制点击区域为圆形
        Shape shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
        return shape.contains(x, y);
    }
}

修改后的Board.java

import java.awt.*;
import javax.swing.*;

public class Board extends JPanel {
    private int width;
    private int height;
    private String title;
    private int gridGap; // 网格每格间距,统一计算避免逻辑不一致

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Board(int width, int height, String title) {
        super();
        this.width = width;
        this.height = height;
        this.title = title;
        this.gridGap = (width - 20) / 9; // 提前计算网格间距,和绘制逻辑统一
        setLayout(null); // 启用绝对定位
        this.initBoard();
        // 测试添加棋子:在(0,0)交叉点放黑子,(1,1)交叉点放白子
        addStone(0, 0, Color.BLACK);
        addStone(1, 1, Color.WHITE);
    }

    public Board() {
        super();
    }

    // 统一添加棋子的方法:i是横向网格序号,j是纵向网格序号,color是棋子颜色
    public void addStone(int i, int j, Color color) {
        StoneButton stone = new StoneButton(color);
        // 计算按钮左上角坐标,中心对齐交叉点
        int x = 10 + i * gridGap - 32;
        int y = 10 + j * gridGap - 32;
        stone.setBounds(x, y, 65, 65);
        add(stone);
    }

    public void initBoard() {
        JFrame f = new JFrame(this.getTitle());
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(this.getWidth(), this.getHeight());
        f.add(this, BorderLayout.CENTER);
        // 不要给JFrame设置FlowLayout,棋子都放在当前Board面板上
        f.setVisible(true);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i = 0; i < 10; i++) {
            g.drawLine(0, 10 + (i * gridGap), this.getWidth(),
                    10 + (i * gridGap));
            g.drawLine(10 + (i * gridGap), 0, 10 + (i * gridGap),
                    this.getHeight());
        }
    }
}

内容的提问来源于stack exchange,提问作者a.v

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:48:01