【问题标题】:ImageIcon method loops infinitelyImageIcon 方法无限循环
【发布时间】:2020-01-16 02:14:31
【问题描述】:

我正在开发一个 Java swing 应用程序,我正在尝试加载国际象棋棋子的图像,并且一切都很好,直到突然,我得到了错误:

Exception in thread "main" java.lang.StackOverflowError
    at java.base/java.lang.String.indexOf(String.java:1612)
    at java.base/java.lang.String.indexOf(String.java:1569)
    at java.base/java.net.URLStreamHandler.parseURL(URLStreamHandler.java:151)
    at java.base/sun.net.www.protocol.file.Handler.parseURL(Handler.java:67)
    at java.base/java.net.URL.<init>(URL.java:696)
    at java.base/java.net.URL.<init>(URL.java:563)
    at java.base/jdk.internal.loader.URLClassPath$FileLoader.getResource(URLClassPath.java:1222)
    at java.base/jdk.internal.loader.URLClassPath$FileLoader.findResource(URLClassPath.java:1211)
    at java.base/jdk.internal.loader.URLClassPath.findResource(URLClassPath.java:294)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findResourceOnClassPath(BuiltinClassLoader.java:499)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findResource(BuiltinClassLoader.java:323)
    at java.base/java.lang.ClassLoader.getResource(ClassLoader.java:1400)
    at java.base/java.lang.Class.getResource(Class.java:2741)
    at model.Board.getImageIcon(Board.java:246)
    at model.Board.setBoard(Board.java:49)
    at model.Board.<init>(Board.java:37)
    at model.Board.getBoardInstance(Board.java:28)
    at controler.FigureAction.<init>(FigureAction.java:15)
    at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)
at model.Board.setBoard(Board.java:49)
at model.Board.<init>(Board.java:37)
at model.Board.getBoardInstance(Board.java:28)
at controler.FigureAction.<init>(FigureAction.java:15)
at model.Figure.<init>(Figure.java:30)

并且来自at model.Board.setBoard(Board.java:49) 的部分在之后被记录了很多次(仅该部分)。 在调试错误时,我看到它一遍又一遍地进入相同的方法,直到发生堆栈溢出错误。在那里,我正在从本地地址检索图像。(以前都有效..) 方法如下:

private ImageIcon getImageIcon(String path,String description) {
        URL imgURL = getClass().getResource(path);
        if (imgURL != null) {
            Image ii=new ImageIcon(imgURL, description).getImage().getScaledInstance(70, 70, Image.SCALE_SMOOTH);
            ImageIcon im=new ImageIcon(ii);
            return im;

        } 
        else {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
    }

它在这里被调用

public void setBoard(Color c1,Color c2,Dimension dim) {

        for(int i=0;i<8;i++) {
            for(int j=0;j<8;j++) {
                Point point=new Point(i,j);
                if ((i+j)%2==0) {
                    if(i==0 && j==0) {
                        ***Figure f=new Figure (null,null,"white_rook",null,getImageIcon("/images/WhiteRook.png",null));***
                        fields[i][j]=new Field(c1,new Position(point.x,point.y),i*8+j,f);
                        f.field=fields[i][j];
                        f.pos=new Position(point.x,point.y);
                        fields[i][j].add(f);
                        figures[i][j]=f;
                    }

它是方法 setBoard 的一部分,它基本上将每一块放在场上。图类看起来像:

public class Figure extends JPanel {

    public Field field;
    public Color color;
    public String name;
    public Movement movement;
    public ImageIcon imageIcon;
    public Position pos;

    public Figure(Field field, Color color, String name, Movement movement, ImageIcon icon) {
        this.field = field;
        this.color = color;
        this.name = name;
        this.movement = movement;
        this.imageIcon = icon;
        this.setPreferredSize(new Dimension(70, 70));
        this.addMouseMotionListener(new FigureAction());
        this.addMouseListener(new FigureAction());
        this.setBackground(null);


    }
}

在这里,我从 png 图像制作缩放的 imageIcon 并将其取回。如果有人能够告诉我可能是什么问题,我将不胜感激。我想我在这里遗漏了一些重要的东西,但目前不知道在哪里可以看到..提前致谢。

【问题讨论】:

  • 调用时path 的值是多少?整个堆栈跟踪是否不止一次显示model.Board.getImageIcon
  • 在调试错误时,我看到它一遍又一遍地输入相同的方法 一遍又一遍地输入哪个方法?谁在一遍又一遍地调用这个方法?
  • @VGR model.Board.getImageIcon 只显示一次,但之后的几行显示了很多次(我重写了上面的堆栈跟踪).. 路径的值是“/images/WhiteRook.png ",这是正确的路径..
  • @Abra 我用三个星号标记了调用 getImageIcon 的方法。
  • 请再添加 20-30 行堆栈跟踪,以便我们了解无限方法调用的来源。

标签: java swing imageicon


【解决方案1】:

第一个 getClass() 实际上可能是一个子类,所以为了良好的顺序:

    URL imgURL = Board.class.getResource(path);

然后,优化内存使用和速度。我忽略这里的描述。

Map<String, ImageIcon> sharedIcons = new HashMap<>();

private ImageIcon getImageIcon(String path, String description) {
    ImageIcon icon = sharedIcons.get(path);
    if (icon == null) {
        URL imgURL = getClass().getResource(path);
        if (imgURL == null) {
            System.err.println("Couldn't find file: " + path);
            return null;
        }
        icon = new ImageIcon(imgURL, description);
        Image ii = new ImageIcon(imgURL, description)
                .getImage().getScaledInstance(70, 70, Image.SCALE_SMOOTH);
        icon = new ImageIcon(ii);

        sharedIcons.put(path, icon);
    }
    return icon;
}

检查没有递归。 FigureAction 打电话给setBoard 左右。

【讨论】:

    【解决方案2】:

    根据您提供的堆栈跟踪和代码:

    at model.Board.setBoard(Board.java:49)
    at model.Board.<init>(Board.java:37)
    at model.Board.getBoardInstance(Board.java:28)
    at controler.FigureAction.<init>(FigureAction.java:15)
    at model.Figure.<init>(Figure.java:30)
    

    意思是:

    1. Figure 构造函数被调用。
    2. 然后FigureAction构造函数被调用。
    3. 然后,在某个时间点,Board.setBoard 被调用。
    4. 但是Board.setBoard 再次调用您刚刚用 3 个星号突出显示的行中的 Figure 构造函数...

    为了解决这个问题,这取决于您要达到的目标。这意味着我们需要更多代码才能查看(例如 MRE),如果您希望我们尝试解决它。​​

    【讨论】:

      猜你喜欢
      • 2014-11-10
      • 1970-01-01
      • 2015-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-15
      • 2019-11-25
      相关资源
      最近更新 更多