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

Java Swing跳棋开发中paintComponent重复添加按钮致界面异常

问题根因
  • 大量极小按钮生成、调整窗口/点击按钮后新增按钮:paintComponent是Swing的界面重绘回调,会在窗口大小变化、控件状态变化、手动调用repaint()时频繁触发,你将按钮创建、add()逻辑写在paintComponent调用的initalprnt()方法中,相当于每次重绘都会新增24个按钮(12绿12蓝)。同时你没有为MainPane设置空布局,setBounds()配置会被默认的FlowLayout忽略,未完成布局计算的按钮都会被堆在面板顶部,显示为极小的异常按钮。
  • 鼠标悬停闪烁:一方面是大量重叠按钮的重绘冲突,另一方面是你为按钮设置了带alpha通道的透明背景,但没有调用setOpaque(false)关闭Swing控件的默认不透明绘制属性,导致悬停时状态绘制异常。
    补充问题:你当前的监听器逻辑只作用在最后创建的1个绿按钮和1个蓝按钮上,其余22个按钮都没有绑定点击事件。
修复方案
  1. 将按钮初始化逻辑从绘制逻辑中剥离,放到MainPane构造方法中,仅在组件初始化时执行一次
  2. 为MainPane设置空布局,让setBounds()配置生效
  3. 调整按钮透明配置,为每个按钮单独绑定监听器
  4. paintComponent仅保留棋盘、棋子的绘制逻辑,不做组件修改操作

修复后核心代码示例

public class MainPane extends JPanel implements MouseListener {
    private GameListener gameListener;

    public MainPane() {
        // 设置空布局,让setBounds生效
        setLayout(null);
        addMouseListener(this);
        // 初始化按钮仅执行一次
        initButtons();
    }

    private void initButtons() {
        int xshift = 125;
        int yshift = 0;
        // 初始化绿方按钮
        for (int i = 0; i < 3; i++) {
            if (i == 2) {
                xshift = 125;
            }
            for (int j = 0; j < 4; j++) {
                JButton green = new JButton();
                green.setBackground(new Color(0, 100, 0, 0));
                green.setOpaque(false); // 关闭默认不透明绘制
                green.setBounds(xshift, yshift, 125, 125);
                green.addActionListener(e -> {
                    System.out.println("绿方按钮触发");
                    gameListener.startNewGame();
                });
                add(green);
                xshift += 250;
            }
            xshift = 0;
            yshift += 125;
        }
        yshift += 250;
        // 初始化蓝方按钮
        for (int k = 0; k < 3; k++) {
            if (k == 2) {
                xshift = 0;
            }
            for (int j = 0; j < 4; j++) {
                JButton blue = new JButton();
                blue.setBackground(new Color(0, 0, 100, 0));
                blue.setOpaque(false);
                blue.setBounds(xshift, yshift, 125, 125);
                blue.addActionListener(e -> {
                    System.out.println("蓝方按钮触发");
                    gameListener.startNewGame();
                });
                add(blue);
                xshift += 250;
            }
            xshift = 125;
            yshift += 125;
        }
    }

    public void setGameListener(GameListener gameListener) {
        this.gameListener = gameListener;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(1000, 1000);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int xshift;
        int yshift = 0;
        // 绘制棋盘
        g.setColor(new Color(0, 0, 0));
        for (int i = 0; i < 4; i++) {
            xshift = 125;
            for (int j = 0; j < 4; j++) {
                g.fillRect(xshift, yshift, 125, 125);
                xshift += 250;
            }
            xshift = 0;
            yshift += 125;
            for (int k = 0; k < 4; k++) {
                g.fillRect(xshift, yshift, 125, 125);
                xshift += 250;
            }
            yshift += 125;
        }
        // 绘制棋子图形
        xshift = 125;
        yshift = 0;
        g.setColor(new Color(0, 100, 0));
        for (int i = 0; i < 3; i++) {
            if (i == 2) {
                xshift = 125;
            }
            for (int j = 0; j < 4; j++) {
                g.fillOval(xshift, yshift, 125, 125);
                xshift += 250;
            }
            xshift = 0;
            yshift += 125;
        }
        yshift += 250;
        g.setColor(new Color(0, 0, 100));
        for (int k = 0; k < 3; k++) {
            if (k == 2) {
                xshift = 0;
            }
            for (int j = 0; j < 4; j++) {
                g.fillOval(xshift, yshift, 125, 125);
                xshift += 250;
            }
            xshift = 125;
            yshift += 125;
        }
    }

    // 其余鼠标事件方法保持不变
    public void mouseClicked(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 01:15:03