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

Graphics2D.drawImage()调用成功但JPanel上图像未显示的问题

JPanel绘制图像不显示问题排查

我正在开发一款类似Window Kill的游戏,需要在JPanel上绘制图像。通过System.out.println()可以确认图像绘制逻辑已经执行,而且线程中也调用了repaint()方法,但运行程序时图像始终无法显示。我试过在paintComponent()里绘制椭圆,椭圆能正常显示;也尝试用JLabel添加图像,同样没效果。相关代码如下:

package org.example.View.GamePagePanels;

import org.example.Controller;
import org.example.Location;
import org.example.View.BossHeadView;
import org.example.View.EntityView;
import org.example.View.EpsilonView;
import org.example.movement.EpsilonKeylistener;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.UUID;

public class BossHeadPanel extends JPanel {
    private boolean Isometric=false;
    private boolean isRigid=false;
    private String ID="";
    public Thread thread;

    public boolean isIsometric() {
        return Isometric;
    }

    public void setIsometric(boolean isometric) {
        Isometric = isometric;
    }

    public boolean isRigid() {
        return isRigid;
    }

    public void setRigid(boolean rigid) {
        isRigid = rigid;
    }

    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID = ID;
    }
    JLabel smiley;
    Image image;

    public BossHeadPanel() {
        setLayout(null);
        ID= UUID.randomUUID().toString();
        setLayout(null);
        setFocusable(true);
        addKeyListener(EpsilonKeylistener.getEpsilonKeylistener());
        setBackground(Color.black);
        setVisible(true);
        ImageIcon icon=new ImageIcon("src/main/resources/icons/boss.png");
        image= icon.getImage();
        smiley=new JLabel();
        smiley.setIcon(icon);
        smiley.setBounds(0,0,100,100);
        smiley.setVisible(true);
        this.add(smiley);

        thread=new Thread(new Runnable() {
            @Override
            public void run() {
                while (Controller.isRunning){
                    ArrayList<EntityView> entities=EntityView.entityViews;
                    for(int i=0;i< entities.size();i++){
                        EntityView ent=entities.get(i);
                        if(isShowing()){
                            if ((ent.location.getX()>=getLocationOnScreen().getX() && ent.location.getX()<=getLocationOnScreen().getX()+getWidth() )||
                                    ( ent.location.getY()>= getLocationOnScreen().getY() && ent.location.getY()<=getLocationOnScreen().getY()+getHeight())){
                                double x=ent.location.getX()-getLocationOnScreen().getX();
                                double y=ent.location.getY()-getLocationOnScreen().getY();
                                ent.panelLocations.put(getID(),new Location(x,y));
                            }
                        }

                    }
                    if(isShowing()){
                        if((EpsilonView.getEpsilonView().getX()>=getLocationOnScreen().getX() && EpsilonView.getEpsilonView().getX()<=getLocationOnScreen().getX()+getWidth() )||
                                ( EpsilonView.getEpsilonView().getY()>= getLocationOnScreen().getY() && EpsilonView.getEpsilonView().getY()<=getLocationOnScreen().getY()+getHeight())){
                            double x=EpsilonView.getEpsilonView().getX()-getLocationOnScreen().getX();
                            double y=EpsilonView.getEpsilonView().getY()-getLocationOnScreen().getY();
                            EpsilonView.epsilonView.panelLocations.put(getID(),new Location(x,y));
                        }
                    }
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    repaint();
                }
            }
        });
        thread.start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2=(Graphics2D) g;
        g2.setColor(Color.green);
        g2.fillOval(0,0,20,20);

        if(image!=null){
            g2.drawImage(image,0,0,100,100,this);
            System.out.println("image drawing");
        }else{
            System.out.println("the image doesn't load");
        }
    }
}

解决方法

  • 修正资源加载路径
    替换图片加载代码为类加载器方式,避免打包后路径失效:

    ImageIcon icon = new ImageIcon(getClass().getResource("/icons/boss.png"));
    

    确保src/main/resources是项目的资源根目录,打包后icons/boss.png会在classpath根目录下。

  • 检查空布局的影响
    空布局需要手动设置所有组件的尺寸和位置,确认JPanel本身的尺寸是否正确设置(比如通过setPreferredSize(new Dimension(xxx, xxx))),父容器是否正确布局这个JPanel。

  • 处理Swing线程安全
    虽然repaint()是线程安全的,但如果后续有UI状态修改操作,建议用SwingUtilities.invokeLater()在EDT线程执行。另外,Controller.isRunning变量需要添加volatile修饰,确保线程能读取到最新值:

    public static volatile boolean isRunning = true;
    
  • 调整图像绘制坐标
    考虑JPanel的内边距,避免图像被边框遮挡:

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2=(Graphics2D) g;
        g2.setColor(Color.green);
        g2.fillOval(0,0,20,20);
    
        if(image!=null){
            Insets insets = getInsets();
            g2.drawImage(image, insets.left, insets.top, 100, 100, this);
            System.out.println("image drawing");
        }else{
            System.out.println("the image doesn't load");
        }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 06:27:03