Percorso errato o sbagliata inizializzazione

di il
3 risposte

Percorso errato o sbagliata inizializzazione

Ciao  ragazzi , sto lavorando a un progetto in Java, e proprio oggi mi sono imbattuto in un grattacapo abbastanza fastidioso da risolvere. Ho voluto delegare la gestione delle immagini a una classe apposita , denominata ImageManager:

package ProgettoVero.src.Utilities;

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

public class ImageManager {
    private BufferedImage[] buffImage;
    private String[] imageNames;

    public ImageManager() throws IOException {
        
        String homeFolder = "ProgettoVero/src/Utilities/png/";
        buffImage = new BufferedImage[27];
        imageNames = new String[7];
        

        // Carica le immagini nel buffer e memorizza i nomi
        buffImage[0] = ImageIO.read(new File(homeFolder + "IconaVita.png"));
        imageNames[0] = "Vita"; // Nome associato
        buffImage[1] = ImageIO.read(new File(homeFolder + "IconaResetCastello.png"));
        imageNames[1] = "Castello"; // Nome associato
       
        buffImage[2] = ImageIO.read(new File(homeFolder + "AbilitaMago.png"));
        buffImage[3] = ImageIO.read(new File(homeFolder + "AbilitaMinotauro.png"));
        buffImage[4] = ImageIO.read(new File(homeFolder + "AbilitaGuerriero.png"));
        buffImage[5] = ImageIO.read(new File(homeFolder + "SferaAbilitaMago.png"));
        buffImage[6] = ImageIO.read(new File(homeFolder + "MinotauroFuria.png"));
        buffImage[7] = ImageIO.read(new File(homeFolder + "AsciaAbilita.png"));
        buffImage[8] = ImageIO.read(new File(homeFolder + "Minotauro.png"));
        buffImage[9] = ImageIO.read(new File(homeFolder + "GuerrieroAbilita.png"));
        buffImage[10] = ImageIO.read(new File(homeFolder + "SpadaAbilita.png"));
        buffImage[11] = ImageIO.read(new File(homeFolder + "Guerriero.png"));
        buffImage[12] = ImageIO.read(new File(homeFolder + "SferaMago.png"));
        buffImage[13] = ImageIO.read(new File(homeFolder + "Spada.png"));
        buffImage[14] = ImageIO.read(new File(homeFolder + "MazzaMinotauro.png"));
        buffImage[15] = ImageIO.read(new File(homeFolder + "Mago.png"));
        buffImage[16] = ImageIO.read(new File(homeFolder + "MagoAnteprima.png"));
        buffImage[17] = ImageIO.read(new File(homeFolder + "OssoMostro1.png"));
        buffImage[18] = ImageIO.read(new File(homeFolder + "PozzaAcidoMostro2.png"));
        buffImage[19] = ImageIO.read(new File(homeFolder + "MazzaMostro3.png"));
        buffImage[20] = ImageIO.read(new File(homeFolder + "MazzaMostro4.png"));
        buffImage[21] = ImageIO.read(new File(homeFolder + "BastoneBoss.png"));
        buffImage[22] = ImageIO.read(new File(homeFolder + "Boss.png"));
        imageNames[2] = "Boss"; // Nome associato
        buffImage[23] = ImageIO.read(new File(homeFolder + "Mostro1.png"));
        imageNames[3] = "Mostro1"; // Nome associato
        
        
        buffImage[24] = ImageIO.read(new File(homeFolder + "Mostro2.png"));
        imageNames[4] = "Mostro2"; // Nome associato
        buffImage[25] = ImageIO.read(new File(homeFolder + "Mostro3.png"));
        imageNames[5] = "Mostro3"; // Nome associato
        buffImage[26] = ImageIO.read(new File(homeFolder + "Mostro4.png"));
        imageNames[6] = "Mostro4"; // Nome associato
    }

    public BufferedImage getImage(int index) {
        return buffImage[index];
    }

    public String getImageName(int index) {
        return imageNames[index];
    }
}

Questa classe inserita nella cartella Utilities, cartella che contiene a sua volta la cartella png da dove prendere le foto. Utilities è contenuta a sua volta in src, che a sua volta è contenuta in ProgettoVero. Ho cominciato così a creare le altre classi , e a provare il funzionamento di quest'ultima, ed effettivamente le immagini venivano mostrate senza problema. Questo fino a che non ho creato un altra classe denominata ComboPersonaggio:

package ProgettoVero.src.View.FrameOpzioni;


import ProgettoVero.src.Model.Personaggio;
import ProgettoVero.src.Utilities.ImageManager;
import ProgettoVero.src.View.CustomButtonOpzioni;
import ProgettoVero.src.Controller.ControllerAudio;


import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;


public class ComboPersonaggio extends JPanel {
    private ImageManager imageManager;
    private JLabel pers; // Etichetta per la selezione del personaggio
    private JComboBox<String> personaggi; // ComboBox per selezionare il personaggio
    private JLabel anteprima; // Etichetta per mostrare l'anteprima del personaggio
    private JLabel descrizione; // Etichetta per mostrare la descrizione del personaggio
    private JLabel vitaLabel; // Etichetta per la vita del personaggio
    private JLabel dannoLabel; // Etichetta per il danno del personaggio
    private JLabel velocitaLabel; // Etichetta per la velocità del personaggio
    private CustomButtonOpzioni confermaPersonaggio; // Pulsante per confermare la selezione del personaggio
    private FrameOpzioni frameOpzioni; // Riferimento al frame delle opzioni
    private ControllerAudio controllerAudio; // Controller per gestire l'audio


    // Costruttore per inizializzare i componenti
    public ComboPersonaggio(FrameOpzioni frameOpzioni) {
        this.frameOpzioni = frameOpzioni;
        setLayout(new BorderLayout(10, 10)); // Layout a BorderLayout
        controllerAudio = new ControllerAudio(); // Inizializza il controller audio
        try {
            // Inizializza l'ImageManager per caricare le immagini
            this.imageManager = new ImageManager();
            System.out.println("ImageManager inizializzato con successo.");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Errore durante l'inizializzazione di ImageManager.");
        }


        // Pannello superiore con etichette e ComboBox
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new GridBagLayout()); // Layout a GridBagLayout
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 5, 5); // Spaziatura tra i componenti


        // Inizializzazione dei componenti
        pers = new JLabel("Seleziona un Personaggio");
        personaggi = new JComboBox<>(new String[]{"Wizard", "Minotauro", "Guerriero"});
        anteprima = new JLabel();
        anteprima.setHorizontalAlignment(JLabel.CENTER);
        anteprima.setVerticalAlignment(JLabel.CENTER);
        descrizione = new JLabel(); // Inizializza la descrizione
        vitaLabel = new JLabel();
        dannoLabel = new JLabel();
        velocitaLabel = new JLabel();


        // Configura GridBagConstraints e aggiungi i componenti al pannello superiore
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        topPanel.add(pers, gbc);


        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.gridwidth = 2;
        topPanel.add(personaggi, gbc);


        gbc.gridx = 3;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.BOTH;
        topPanel.add(anteprima, gbc);


        JPanel statsPanel = new JPanel();
        statsPanel.setLayout(new GridLayout(3, 1, 5, 5));
        statsPanel.add(vitaLabel);
        statsPanel.add(dannoLabel);
        statsPanel.add(velocitaLabel);


        gbc.gridx = 4;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.fill = GridBagConstraints.VERTICAL;
        topPanel.add(statsPanel, gbc);


        // Pannello inferiore con il pulsante di conferma
        JPanel bottomPanel = new JPanel();
        confermaPersonaggio = new CustomButtonOpzioni("Conferma Personaggio");
        bottomPanel.add(confermaPersonaggio);


        // Aggiungi i pannelli al layout principale
        add(topPanel, BorderLayout.CENTER);
        add(bottomPanel, BorderLayout.SOUTH);


        // Aggiungi ActionListener alla ComboBox e al pulsante di conferma
        personaggi.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String selectedItem = (String) personaggi.getSelectedItem();
                updateAnteprima(selectedItem);
            }
        });


        confermaPersonaggio.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String selectedItem = (String) personaggi.getSelectedItem();
                confermaSelezione(selectedItem);
            }
        });
    }


    // Aggiorna l'anteprima del personaggio selezionato
    private void updateAnteprima(String characterName) {
        ImageIcon icon = null;
        String vita = "";
        String danno = "";
        String velocita = "";


        // Aggiorna i dettagli in base al personaggio selezionato
        switch (characterName) {
            case "Wizard":
                icon = new ImageIcon(imageManager.getImage(16));
                controllerAudio.playSound("C:\\Users\\andre\\OneDrive\\Desktop\\Programmazione\\Progetto\\Audio\\EffettiSonori\\Anteprime\\MagoAnteprima.wav");
                break;
            case "Minotauro":
            icon = new ImageIcon(imageManager.getImage(8));
                controllerAudio.playSound("C:\\Users\\andre\\OneDrive\\Desktop\\Programmazione\\Progetto\\Audio\\EffettiSonori\\Anteprime\\MinotauroAnteprima.wav");
                break;
            case "Guerriero":
            icon = new ImageIcon(imageManager.getImage(11));
                controllerAudio.playSound("C:\\Users\\andre\\OneDrive\\Desktop\\Programmazione\\Progetto\\Audio\\EffettiSonori\\Anteprime\\GuerrieroAnteprima.wav");
                break;
        }


        // Aggiorna l'icona e le etichette con i dettagli del personaggio
        anteprima.setIcon(icon);
        vitaLabel.setText(vita);
        dannoLabel.setText(danno);
        velocitaLabel.setText(velocita);
        descrizione.setText(""); // Pulisce la descrizione
    }


    // Conferma la selezione del personaggio e aggiorna il frame delle opzioni
    private void confermaSelezione(String characterName) {
        BufferedImage icon = null;
        int vita = 0;
        int danno = 0;
        int velocita = 0;
        String descrizioneText = "";


        // Aggiorna i dettagli del personaggio in base alla selezione
        switch (characterName) {
            case "Wizard":
                icon = imageManager.getImage(15);
                vita = 2;
                danno = 25;
                velocita = 7;
                descrizioneText = "<html>Il mago è un potente incantatore,<br>specializzato in magie a distanza.</html>";
                break;
            case "Minotauro":
                icon = imageManager.getImage(8);
                vita = 4;
                danno = 30;
                velocita = 4;
                descrizioneText = "<html>Il minotauro è un feroce combattente,<br>con grande forza fisica.</html>";
                break;
            case "Guerriero":
                icon = imageManager.getImage(11);
                vita = 3;
                danno = 20;
                velocita = 5;
                descrizioneText = "<html>Il guerriero è un abile combattente<br>con grande resistenza.</html>";
                break;
        }


        // Crea un oggetto Personaggio e aggiorna la selezione nel frame delle opzioni
        Personaggio personaggio = new Personaggio(characterName, velocita, danno, vita, icon, 0, 0);
        frameOpzioni.setSelectedPersonaggio(personaggio);


        // Mostra un messaggio di conferma
        JOptionPane.showMessageDialog(frameOpzioni,
                "Personaggio Selezionato: " + characterName + "\n" +
                "Vita: " + vita + "\n" +
                "Descrizione:\n" + descrizioneText,
                "Conferma Personaggio",
                JOptionPane.INFORMATION_MESSAGE);
    }
}

Che inizialmente funzionava senza problemi , con la logica applicata. Andando avanti , la parte che riguarda questo pannello ha smesso di funzionare,senza mostrare piu le immagini , e stampando su console l'errore:

javax.imageio.IIOException: Can't read input file!
       at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1308)
       at ProgettoVero.src.Utilities.ImageManager.<init>(ImageManager.java:41)
       at ProgettoVero.src.View.FrameOpzioni.ComboPersonaggio.<init>(ComboPersonaggio.java:35)
       at ProgettoVero.src.View.FrameOpzioni.FrameOpzioni.<init>(FrameOpzioni.java:37)
       at ProgettoVero.src.View.FrameMenu.BottoneOpzioni$1.actionPerformed(BottoneOpzioni.java:24)
       at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
       at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
       at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
       at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
       at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
       at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:297)
       at java.desktop/java.awt.Component.processMouseEvent(Component.java:6620)
       at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
       at java.desktop/java.awt.Component.processEvent(Component.java:6385)
       at java.desktop/java.awt.Container.processEvent(Container.java:2266)
       at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
       at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
       at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
       at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
       at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
       at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
       at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
       at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
       at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
       at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
       at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
       at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
       at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
       at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
       at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
       at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
       at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
       at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
       at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
       at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
       at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
       at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
       at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
       at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
       at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
       at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Errore durante l'inizializzazione di ImageManager.
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "ProgettoVero.src.Utilities.ImageManager.getImage(int)" because "this.imageManager" is null
       at ProgettoVero.src.View.FrameOpzioni.ComboPersonaggio.updateAnteprima(ComboPersonaggio.java:126)
       at ProgettoVero.src.View.FrameOpzioni.ComboPersonaggio$1.actionPerformed(ComboPersonaggio.java:103)
       at java.desktop/javax.swing.JComboBox.fireActionEvent(JComboBox.java:1294)
       at java.desktop/javax.swing.JComboBox.setSelectedItem(JComboBox.java:619)
       at java.desktop/javax.swing.JComboBox.setSelectedIndex(JComboBox.java:654)
       at java.desktop/javax.swing.plaf.basic.BasicComboPopup$Handler.mouseReleased(BasicComboPopup.java:946)
       at java.desktop/java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:298)
       at java.desktop/java.awt.Component.processMouseEvent(Component.java:6620)
       at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
       at java.desktop/javax.swing.plaf.basic.BasicComboPopup$1.processMouseEvent(BasicComboPopup.java:551)
       at java.desktop/java.awt.Component.processEvent(Component.java:6385)
       at java.desktop/java.awt.Container.processEvent(Container.java:2266)
       at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
       at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
       at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
       at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
       at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
       at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
       at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
       at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
       at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
       at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
       at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
       at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
       at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
       at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
       at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
       at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
       at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
       at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
       at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
       at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
       at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
       at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
       at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
       at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
       at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
       at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Ho messo mano al codice e provato a debuggare in diversi modi , ma non sono giunto a nessuna soluzione. L'errore inziale sembra essere un errore di lettura del file , come se non venisse trovato , il che è strano in quanto non ho toccato niente che riguardasse la parte delle immagini , e in più che funzionava in precedenza .Il secondo errore che si genera è legato all'inizializzazione del ImageManager, ma ripeto , anche questo in precedenza era stato provato. Ovviamente vi mostro questa classe perchè leggendo gli errori sembrerebbe quella incriminata, ma non trovo soluzioni , qualcuno potrebbe aiutarmi?

3 Risposte

  • Re: Percorso errato o sbagliata inizializzazione

    04/09/2024 - biagio-23 ha scritto:


            String homeFolder = "ProgettoVero/src/Utilities/png/";

    La questione fondamentale è che hai usato un percorso “relativo” alla directory “corrente” (che quale sia è vago perché dipende da vari fattori) e nel path hai messo oltretutto la “src”. Questo percorso, ammesso che funzioni, è comunque valido solo nel tuo ambiente di sviluppo sulla tua macchina.

    Se dovessi poi impacchettare il progetto in un jar “eseguibile” da dare ad altri … semplicemente non funzionerà più niente delle immagini, perché la “src” non esisterà più così come la “ProgettoVero”.

    Le immagini (e le risorse in generale) o si caricano tramite il concetto delle “risorse” lungo il classpath (con il getResource/getResourceAsStream di java.lang.Class) oppure si stabiliscono altre regole legate ad una directory specifica o “notevole”.

  • Re: Percorso errato o sbagliata inizializzazione

    04/09/2024 - andbin ha scritto:


    04/09/2024 - biagio-23 ha scritto:


            String homeFolder = "ProgettoVero/src/Utilities/png/";

    La questione fondamentale è che hai usato un percorso “relativo” alla directory “corrente” (che quale sia è vago perché dipende da vari fattori) e nel path hai messo oltretutto la “src”. Questo percorso, ammesso che funzioni, è comunque valido solo nel tuo ambiente di sviluppo sulla tua macchina.

    Se dovessi poi impacchettare il progetto in un jar “eseguibile” da dare ad altri … semplicemente non funzionerà più niente delle immagini, perché la “src” non esisterà più così come la “ProgettoVero”.

    Le immagini (e le risorse in generale) o si caricano tramite il concetto delle “risorse” lungo il classpath (con il getResource/getResourceAsStream di java.lang.Class) oppure si stabiliscono altre regole legate ad una directory specifica o “notevole”.

    Però quello che non capisco è perché prima funzionava e ora no , nel senso l'inizializzazione mi sembra giusta , a parere tuo è il percorso relativo il problema? Quale potrebbe essere una soluzione ?

  • Re: Percorso errato o sbagliata inizializzazione

    Se le immagini sono parte fissa della applicazione, il modo più corretto è caricarle come “risorse” in classpath nel senso descritto dai getResource e getResourceAsStream di java.lang.Class.

    Se hai una classe il cui nome completamente qualificato è per es. com.esempio.ImageManager e in quello stesso package com.esempio ci metti una immagine Boss.png, allora:

    URL url = ImageManager.class.getResource("Boss.png");

    oppure

    InputStream is = ImageManager.class.getResourceAsStream("Boss.png");

    Ottieni un URL o InputStream alla risorsa. Esiste un ImageIO.read() per entrambi ma attenzione che il read(InputStream) NON chiude lo stream (la chiusura è a tuo carico), quindi nel tuo caso probabilmente è più conveniente usare l'URL.

    Negli esempi sopra, la specifica della risorsa (cioè "Boss.png") è relativa al package della classe ImageManager. E non c'entrano le directory o peggio la directory “corrente”. Viene tutto risolto secondo il classpath e quindi vale e funziona sia quando i .class/.png sono “sfusi” sul file-system, sia quando vengono poi impacchettati in un .jar da dare ad altri.

Devi accedere o registrarti per scrivere nel forum
3 risposte