Как получить доступ к ресурсам в JAR файле?

У меня есть проект Java с панелью инструментов, и на панели инструментов есть значки. Эти значки хранятся в папке с именем resources/, поэтому, например, путь может быть "resources/icon1.png". Эта папка находится в моем каталоге src, поэтому, когда она компилируется, папка копируется в bin/

Я использую следующий код для доступа к ресурсам.

    protected AbstractButton makeToolbarButton(String imageName, String actionCommand, String toolTipText,
        String altText, boolean toggleButton) {

    String imgLocation = imageName;
    InputStream imageStream = getClass().getResourceAsStream(imgLocation);

    AbstractButton button;
    if (toggleButton)
        button = new JToggleButton();
    else
        button = new JButton();

    button.setActionCommand(actionCommand);
    button.setToolTipText(toolTipText);
    button.addActionListener(listenerClass);

    if (imageStream != null) { // image found
        try {
            byte abyte0[] = new byte[imageStream.available()];
            imageStream.read(abyte0);

            (button).setIcon(new ImageIcon(Toolkit.getDefaultToolkit().createImage(abyte0)));

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                imageStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    } else { // no image found
        (button).setText(altText);
        System.err.println("Resource not found: " + imgLocation);
    }

    return button;
}

(imageName будет "resources/icon1.png" и т.д.). Это отлично работает при запуске в Eclipse. Однако, когда я экспортирую исполняемый JAR из Eclipse, значки не найдены.

Я открыл файл JAR, и там была папка ресурсов. Я пробовал все, перемещая папку, изменяя файл JAR и т.д., Но я не могу получить значки для отображения.

Кто-нибудь знает, что я делаю неправильно?

(В качестве побочного вопроса, есть ли какой-либо монитор файлов, который может работать с файлами JAR? Когда возникают проблемы с путями, я обычно просто открываю FileMon, чтобы посмотреть, что происходит, но он просто появляется как доступ к файлу JAR в этом случае)

Спасибо.

Ответ 1

Чтобы загрузить изображение из ресурса JAR, используйте следующий код:

Toolkit tk = Toolkit.getDefaultToolkit();
URL url = getClass().getResource("path/to/img.png");
Image img = tk.createImage(url);
tk.prepareImage(img, -1, -1, null);

Ответ 2

Я вижу две проблемы с вашим кодом:

getClass().getResourceAsStream(imgLocation);

Предполагается, что файл изображения находится в той же папке, что и файл .class класса, из которого этот код отправлен, а не в отдельную папку ресурсов. Вместо этого попробуйте:

getClass().getClassLoader().getResourceAsStream("resources/"+imgLocation);

Другая проблема:

byte abyte0[] = new byte[imageStream.available()];

Метод InputStream.available() не возвращает общее количество байтов в потоке! Он возвращает количество доступных байтов без блокировки, что часто намного меньше.

Вам нужно написать цикл, чтобы скопировать байты во временный ByteArrayOutputStream до тех пор, пока не будет достигнут конец потока. В качестве альтернативы используйте getResource() и createImage() метод, который принимает параметр URL.

Ответ 3

Раздел из руководства Swing по Как использовать значки показывает вам, как создать URL-адрес и прочитать значок в двух утверждениях.

Ответ 4

Например, в проекте NetBeans создайте папку ресурсов в папке src. Поместите свои изображения (jpg,...) там.

Если вы используете ImageIO или Toolkit (включая getResource), вы должны указать ведущий/путь к файлу изображения:

Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resources/agfa_icon.jpg"));
setIconImage(image);

Если этот код находится внутри вашего класса JFrame, изображение добавляется к кадру в виде значка в строке заголовка.