чтение PNG с использованием нулевого исключения ввода ImageIO

Я пытаюсь создать базовую реализацию Pacman для своего курса Java и создал тестовый проект только для того, чтобы заставить движение работать (пока). Я собираюсь попробовать переместить JLabel по панели и установить значок JLabel в виде PNG-файла, который я загрузил в проект. Файл PNG находится в папке с именем Images, а все остальные мои классы находятся в папке src в том же проекте. Когда я пытаюсь прочитать файлы PNG из моих классов папки src, я получаю следующую ошибку:

Exception in thread "main" java.lang.IllegalArgumentException: input == null!
    at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1400)
    at pacman.<init>(pacman.java:16)
    at screen.<init>(screen.java:9)
    at driver.main(driver.java:6)

driver создает объект screen, который затем создает объект pacman, и ошибка указывает на класс pacman, который показан ниже:

import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;

public class pacman {
    Point pacLoc= new Point(0,0);
    Direction pacDir=Direction.RIGHT;
    int pacLives;
    static int count=1;
    int pacID;
    BufferedImage pactest;

    @SuppressWarnings("unused")
    pacman(){
        pacID=count;
        switch(pacID) {
        case 1:
            try {
                pactest=ImageIO.read(getClass().getResource("Images/lolface.png"));
            } catch(IOException a1) {
                a1.printStackTrace();
            }
            pacLoc.setLocation(100,100);
            break;
        case 2:
            try {
                pactest=ImageIO.read(getClass().getResource("Images/whyface.png"));
            } catch(IOException a1) {
                a1.printStackTrace();
            }
            pacLoc.setLocation(100,200);
            break;
        }
        count++;
    }
}

Ошибка возникает (я думаю) из-за того, что ImageIO не находит файлы PNG. Должен ли я как-то импортировать их в мой класс pacman? Каким будет синтаксис импорта в этом случае? Я должен упомянуть, что я использую Eclipse IDE и стараюсь избегать использования каких-либо внешних библиотек для простоты.

Редактировать:

Два других класса на данный момент не слишком велики, поэтому я могу опубликовать их здесь, если это вообще поможет.

Редактировать 2:

Использование ImageIO.read(pacman.class.getResource("lolface.png")); вместо Images/lolface.png работает. Спасибо!


person Bot Fred    schedule 24.11.2019    source источник


Ответы (1)


getClass().getResource() неверно; правильный синтаксис - pacman.class.getResource(...), где pacman - ваше собственное имя класса*.

Во-вторых, ваша обработка исключений нарушена. Исключения содержат 4 полезных вещи (тип, сообщение, трассировку стека и причинно-следственную цепочку).

Вы выбрасываете 3 из 4 вещей. Не делай этого; либо на самом деле иметь дело с этим (ошибки регистрации или печати НЕ имеют дело с этим!), либо бросить его дальше (поместите throws IOException в подпись вашего метода/конструктора), или, если это тоже бесполезно, используйте catch (Whatever e) { throw new RuntimeException(e); } что не очень хорошо, но чертовски лучше, чем e.printStackTrace().

Вам не нужно ничего импортировать; import использует псевдонимы имен типов (import com.foo.Bar; означает: в любое время в этом файле Bar записывается и указывает тип, представьте, что вместо этого он читает com.foo.Bar. Он не загружает класс Bar в память и не запускает какой-либо код внутри него, и это не имеет ничего общего с Ресурсы).

Без трассировки стека ошибки мы не сможем вам помочь.

ЕСЛИ это исключение нулевого указателя в строке, начинающейся с case 1, или в строке, начинающейся с case 2, да, это потому, что ресурс не найден.

Предполагая, что вы исправили указанную выше проблему (pacman.class.getResource вместо getClass().getResource), и это все еще происходит: метод работы getResource заключается в том, что он выглядит относительно каталога, содержащего pacman.class... даже если указанный класс находится, скажем, внутри jar-файла. Итак, если у вас есть, скажем, /home/BotFred/workspace/com.botfred.pacman/build/com/botfred/pacman/pacman.class, то он ожидает, что изображение будет в /home/BotFred/workspace/com.botfred.pacman/build/com/botfred/pacman/Images/lolface.png.

Если вы не совсем уверены, откуда загружается класс pacman, вы всегда можете сделать это, чтобы узнать:

System.out.println(pacman.class.getResource("pacman.class"));

напечатанный результат будет чем-то вроде file:///home/BotFred/workspace/com.botfred.pacman/build/com/botfred/pacman/pacman.class или, возможно, jar:file:///home/BotFred/pacman.jar!com/foo/botfred/pacman.class (что указывает, где находится банка, а затем внутри нее, поскольку банки - это просто zip-файлы, какое место; затем он будет искать внутри этой банки в com/foo/botfred/Images/ lolface.png для вашего изображения.

*) Причина в том, что getClass() использует фактический тип объекта, а не тот код, который вы просматриваете. Итак, если вы создадите подкласс, все сломается. Возможно, у pacman в настоящее время нет подкласса, но ключевое слово есть в настоящее время. Может быть, однажды это так. Будет хреново, если вдруг сломается. Лучше всего научиться хорошей привычке с самого начала; всегда используйте myclassname.class.getResource, потому что это соответствует тому, что вы пытаетесь выполнить (а именно: используйте ресурс, который хранится в том же месте, что и файл класса, в котором хранится этот код).

person rzwitserloot    schedule 25.11.2019
comment
спасибо за ваш подробный ответ! Вместо этого я просто попробовал pacman.class.getResource, и ошибка не исчезла. Я попытаюсь обработать исключение так, как вы описали далее, и вернусь к вам. Класс pacman находится в Pacman/src/pacman.java, а PNG — в Pacman/Images/asd.png Редактировать: запуск Sys.println: file:/C:/*censored*/eclipse-workspace/Pacman/bin /pacman.класс - person Bot Fred; 25.11.2019
comment
Я думаю, что вижу проблему. Папка «Изображения» не находится внутри папки bin (или src), в которой находятся все остальные мои классы. Обе папки находятся на одном уровне. Насколько я понимаю, прямо сейчас он ищет папку с изображениями, которая находится в той же папке, что и pacman.class, когда папка, которую я хочу найти, находится на один слой выше? - person Bot Fred; 25.11.2019
comment
Поместите изображения в то же место, что и исходные файлы Java (таким образом, src/Images/asd.png, а не /Images/asd.png); eclipse автоматически скопирует их в корзину. Невозможно использовать getResource и перейти «на один уровень вверх», но позволить eclipse скопировать их будет работать. - person rzwitserloot; 25.11.2019