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

Java Swing JFrame内JPanel绘制Image图片不显示问题

问题原因
  • 图片加载逻辑不可靠:Toolkit.getDefaultToolkit().getImage()是异步非阻塞方法,调用后会立刻返回,不会等待图片实际加载完成,且代码中加载图片、字体时的异常被空捕获,一旦文件路径错误、加载失败,只会返回null,没有任何报错提示,完全无法定位问题。同时你把图片加载逻辑放在paint方法内,每次界面重绘都会重新触发加载,性能差且极易加载失败。
  • Swing绘制写法不规范:直接重写JPanel的paint方法且未调用super.paint(g),破坏了Swing原生的组件绘制链路,很容易出现渲染异常、元素不显示的问题。Swing自定义绘制标准写法是重写paintComponent方法,且第一行必须调用父类方法完成基础绘制。
  • 窗口初始化顺序错误:你在往JFrame添加自定义棋盘面板之前就调用了setVisible(true),还重复调用了两次该方法,会导致首次界面渲染时组件层级未初始化完成。另外手动给面板设置bounds的写法不符合Swing布局管理器逻辑,且绘制格子尺寸时直接取JFrame的宽高,没有排除窗口边框、标题栏占用的像素,坐标计算容易偏移。
  • 绘制逻辑存在小bug:绘制左上角棋子时y方向坐标用了screen.getWidth()/8而非高度值计算,虽然y=0时暂时看不出问题,但属于逻辑隐患。
修复方案
  1. 替换图片加载方式,提前缓存图片资源
    用ImageIO.read()做同步阻塞加载,启动时就把棋子图片加载到内存缓存,加载失败直接打印异常栈方便排查,资源读取用类加载器路径,避免工作目录变化导致找不到文件:
    public static final class Rook extends Piece{
        private static BufferedImage whiteRook;
        private static BufferedImage blackRook;
        // 类加载时就初始化图片,只加载一次
        static {
            try {
                // 把两张棋子png放到项目src根目录,编译后会自动输出到类路径根目录
                whiteRook = ImageIO.read(Rook.class.getResourceAsStream("/75_px_white_rook.png"));
                blackRook = ImageIO.read(Rook.class.getResourceAsStream("/75_px_black_rook.png"));
            } catch (IOException e) {
                // 禁止空捕获异常,打印堆栈方便定位路径、加载错误
                e.printStackTrace();
            }
        }
    
        public static BufferedImage getWhiteRook(){
            return whiteRook;
        }
        public BufferedImage getBlackRook(){
            return blackRook;
        }
    }
    
  2. 调整窗口初始化顺序,所有组件配置完成后再显示窗口
    删掉createNewBoard方法里提前写的两次setVisible(true)调用,等所有组件添加、参数配置完成后,最后再调用pack()和setVisible(true)。删掉手动给棋盘面板设置bounds的代码,改用setPreferredSize指定面板尺寸,交给布局管理器自动适配。
  3. 修正自定义面板的绘制逻辑
    把重写paint改成重写paintComponent,第一行调用super.paintComponent(graphic),格子尺寸用面板自身的宽高计算(不要用JFrame的宽高),提前在面板初始化时拿到棋子图片引用,不要在绘制循环里反复加载:
    JPanel board = new JPanel(){
        boolean color = true;
        private final Image whiteRook = Piece.Rook.getWhiteRook();
        @Override
        protected void paintComponent(Graphics graphic) {
            super.paintComponent(graphic);
            graphic.setFont(new Font("AlphaRomaineFont.ttf", Font.PLAIN, 18));
            // 基于当前面板尺寸计算格子大小,避免边框、标题栏导致尺寸偏移
            int cellWidth = getWidth() / 8;
            int cellHeight = getHeight() / 8;
    
            for(int y = 0; y < 8; y++){
                for(int x = 0; x < 8; x++){
                    graphic.setColor(color ? Color.decode("#f5f1e6") : Color.decode("#449e48"));
                    graphic.fillRect(x*cellWidth, y*cellHeight, cellWidth, cellHeight);
    
                    if(y == 7){
                        graphic.setColor(Color.BLACK);
                        graphic.drawString(String.valueOf(x_AxisMap.get(x)), x*cellWidth+3,  y*cellHeight+87);
                        graphic.setColor(color ? Color.decode("#f5f1e6") : Color.decode("#449e48"));
                    }
    
                    if(x == 7){
                        graphic.setColor(Color.BLACK);
                        graphic.drawString(String.valueOf(y_AxisMap.get(y)), x*cellWidth+80,  y*cellHeight+15);
                        graphic.setColor(color ? Color.decode("#f5f1e6") : Color.decode("#449e48"));
                    }
                    // 绘制左上角白车,判空避免图片加载失败时报错
                    if(x == 0 && y == 0 && whiteRook != null){
                        graphic.drawImage(whiteRook, x*cellWidth, y*cellHeight, cellWidth, cellHeight, this);
                    }
                    color = !color;
                }
                color = !color;
            }
        } 
    };
    board.setPreferredSize(new Dimension(720,720));     
    screen.add(board);
    // 所有配置完成后再调整窗口位置、大小、显示
    screen.pack();
    screen.setLocationRelativeTo(null);
    screen.setVisible(true);
    
额外注意事项
  • 所有绘制相关的方法(paint/paintComponent)会在窗口移动、缩放、重绘时被频繁调用,不要在这些方法里写加载文件、创建对象这类重IO/重内存逻辑,否则会导致界面卡顿、资源加载异常。
  • 自定义字体也建议和图片一样,启动时一次性加载完成缓存,不要每次设置字体时重新读取文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:31:00