Как получить изображения для загрузки из файла jar?

У меня есть простая игра, которая работает как JApplet. Когда я тестирую его в Eclipse, он работает отлично. Однако, когда я экспортирую его как апплет и пытаюсь протестировать в браузере, он не может найти изображения. Структура папок внутри файла jar выглядит следующим образом:

index.html (page that displays the applet)  
shipyard.jar  
_shipyard  
__Shipyard.class (main applet class)  
_img  
__All of my images, saved as .png files  

Код HTML, используемый для отображения апплета, выглядит следующим образом:

<object width="1280" height="720" data="shipyard.jar" type="application/x-java-applet">
    <param name="archive" value="shipyard.jar">
    <param name="code" value="shipyard.Shipyard">
    <param name="align" value="middle">
</object>

Мои методы init() и run(), которые настраивают очередь предварительной загрузки, а затем перебирают ее для извлечения и подготовки изображений:

@Override
public void init(){ 
    markImageForPreload("background");
    markImageForPreload("shipyard_interior");
    markImageForPreload("tooltip");
    markImageForPreload("button");
    for(String s : ShipyardExterior.tilePages) markImageForPreload("tiles/" + s);
    for(ShipSystem sys : ShipSystem.allSystems){
        markImageForPreload("system/interior/" + sys.imgName);
        if(sys.getForceExterior()) markImageForPreload("system/exterior/" + sys.imgName);
    }   
    for(ShipWeapon wep : ShipWeapon.allWeapons){
        markImageForPreload("weapon/" + wep.imgname);
    }

    currentScreen = new LoadingScreen();

    addMouseListener(this);
    addKeyListener(this);
}

@Override
public void run() {

    preloadCount = 0;       
    preloadTotal = preloadQueue.size();

    for(String s : preloadQueue){
        this.prepareImage(getOrLoadImage(s), this);
        preloadCount++;
        repaint();
    }              

    currentScreen = new ShipyardInterior();

    while(true){
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        try {
            if(this.getMousePosition() != null){
                mouseX = this.getMousePosition().x / 2;
                mouseY = this.getMousePosition().y / 2;
            }
        } catch (NullPointerException e){}
        currentScreen.onUpdate();
        repaint();
        try {
            Thread.sleep(1000 / 60);
        } catch(InterruptedException e) {}

        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
    }
}

Метод из класса JApplet, загружающий и извлекающий изображения:

public static Image getOrLoadImage(String s){
    Image img = instance.loadedImages.get(s);
    if(img == null){
        System.out.println("Loading " + s + ".png.");
        try {
            img = ImageIO.read(new URL(instance.getCodeBase(), "../img/" + s + ".png"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(img == null) System.out.println("Image does not exist.");
        else instance.loadedImages.put(s, img);
    }
    return img;
}

«loadedImages» — это статическая HashMap, которая хранит изображения по их URL-адресам. Когда метод вызывается, он сначала проверяет, загружено ли изображение. Если это так, он возвращает изображение. Если он не загружен, он загружает его и добавляет свой экземпляр Image в загруженные изображения.

Когда я открываю страницу, апплет запускается, но изображения не отображаются. Такие вещи, как drawString(), drawRect() и другие базовые методы рендеринга, работают, но не изображения.

Я перерыл весь интернет и не нашел ничего полезного по этому вопросу. В одном потоке мне сказали самостоятельно подписать банку апплета, что я и сделал, но, похоже, это не сработало. Я играл с различными методами получения изображений (включая getClass().getClassLoader().getRescource()), устанавливая кодовую базу и т. д., но безрезультатно. Какие-либо предложения?


person Community    schedule 01.09.2013    source источник
comment
Любые примеры URL-адресов в loadedImages HashMap? Возможно, это URL-адреса file://, которые работают в Eclipse, но не как апплет?   -  person Drew MacInnis    schedule 02.09.2013
comment
Это не были URL-адреса file://, но это помогло мне найти проблему. Оказывается, вызов getResource возвращал разные пути при тестировании и в браузере.   -  person    schedule 02.09.2013


Ответы (1)


img = ImageIO.read(new URL(instance.getCodeBase(), "../img/" + s + ".png"));

Если бы у меня было время, было бы здорово услышать ваши рассуждения о том, почему это должно работать для описанной структуры. AFAIU должно быть:

img = ImageIO.read(this.getClass().getResource("/img/" + s + ".png"));
person Andrew Thompson    schedule 02.09.2013