Метод ImageIcon зацикливается бесконечно - PullRequest
0 голосов
/ 15 января 2020

Я работаю над приложением 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, который в основном размещает каждый фрагмент на поле. Класс Figure выглядит следующим образом:

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);


    }
}

Здесь я делаю масштабированное изображение image из png-изображения и извлекаю его обратно. Я был бы очень признателен, если кто-то может сказать мне, в чем может быть проблема. Я думаю, что упускаю что-то важное здесь, но в настоящее время не знаю, где еще посмотреть .. Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 15 января 2020

Сначала 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 или около того.

1 голос
/ 15 января 2020

Согласно вашей трассировке стека и предоставленному коду:

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 снова вызывает конструктор Figure в строке, которую вы только что выделили, с 3 звездочками. ..

Чтобы решить эту проблему, это зависит от того, чего вы пытаетесь достичь. Это означает, что нам нужно еще больше кода (например, MRE ), если вы хотите, чтобы мы попытались его решить.

...