Visualizzazione dei risultati da 1 a 7 su 7

Discussione: fat jar con immagini

  1. #1
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16

    fat jar con immagini

    Rieccomi qui a dare fastidio
    Ho terminato la mia bella applicazione, la voglio distribuire ed allo stesso tempo non voglio che lasciare un unico file in mano all'utilizzatore finale (evitiamo che l'user "scassi" il giocattolo).

    Quello che ho fatto:
    [list=1][*]ho messo la cartella immagini nella directory "src" del progetto[*]ho modificato il file "build.xml" come indicato sul web[*]ho dato un bel clean & build[*]ho verificato che nel jar file ci sia la cartella (e ci sta)[/list=1]
    funziona tutto eccetto la visualizzazione delle immagini.

    ecco il codice [uso un progetto di test per fare prima]
    codice:
    package locationjlabeltest;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.event.ItemEvent;
    import java.awt.event.ItemListener;
    import javax.swing.ImageIcon;
    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JLayeredPane;
    import javax.swing.JPanel;
    
    public class LocationJLabelTest extends JFrame{
        private JLayeredPane vassoio;
        private static JPanel pannello3=new JPanel();
        public LocationJLabelTest(){
            super ("testJLabelLocation");
            this.setMinimumSize(new Dimension(400, 400));
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
            
            location2(this);
        }
        
        
        public void location2(JFrame frame){
            
            JPanel pannello=new JPanel();
            JPanel sfondo=new JPanel();
            sfondo.setBackground(Color.YELLOW);
            sfondo.setBounds(0,0, 400,400);
            pannello.setBackground(Color.black);
            pannello.setBounds(100, 200, 100,100);
            System.out.println(getClass().getResource("./images/icona.png"));
            
    /* Strada che dovrei seguire, ma non funziona!!! */
    //        JLabel a=new JLabel(new ImageIcon(getClass().getResource("./images/icona.png")));
            
    /* Strada che funziona ma non mostra le immagini */        
            JLabel a=new JLabel(new ImageIcon("./images/icona.png"));
            
            ItemListener itemListener = new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent itemEvent) {
                int state = itemEvent.getStateChange();
                if (state == ItemEvent.SELECTED) {
    
                    JPanel pannello2=new JPanel();
                    pannello2.setBackground(Color.red);
                    pannello2.setOpaque(true);
    
                    pannello2.setBounds(300, 100,50,50);                
                    vassoio.add(pannello2,new Integer(4));
                    
                   pannello3.setVisible(true);
                    System.out.println("settato!");
                }
                else{
                    System.out.println("De settato!");
                    pannello3.setVisible(false);
                    vassoio.remove(0);
    
                    repaint();
                    }   
                }
            };    
            
            pannello.add(a);
            JCheckBox box=new JCheckBox("prova");
            box.addItemListener(itemListener);
            box.setOpaque(false);
    
            JPanel boxed=new JPanel();
            boxed.setOpaque(false);
            boxed.add(box);
            boxed.setBounds(10, 20, 100,50);
            
            vassoio=new JLayeredPane();
            vassoio.add(boxed,new Integer(2));
            vassoio.add(pannello,new Integer(1));
            vassoio.add(sfondo,new Integer(0));
    
                    pannello3.setBackground(Color.blue);
                    pannello3.setOpaque(true);
                    pannello3.setVisible(false);
                    pannello3.setBounds(300, 220,50,50);                
                    vassoio.add(pannello3,new Integer(3)); 
    
            frame.add(vassoio);
            frame.setVisible(true);        
        }
        
        public static void main(String[] args) {
            LocationJLabelTest l=new LocationJLabelTest();
        }
    }
    Come spiegato con i commenti nel codice la soluzione ai mali del mondo sarebbe quella di usare:
    codice:
    JLabel a=new JLabel(new ImageIcon(getClass().getResource("./images/icona.png")));
    ma l'applicazione non parte nemmeno!!! (potrei provare a lanciare il portatile, ma partirebbe nel modo errato )

    Se invece uso:
    codice:
    JLabel a=new JLabel(new ImageIcon("./images/icona.png"));
    mi parte l'applicazione ma non sivedono le immagini...

    Invocare, invano o meno, tutte le divinità di tutte le religioni non è stato utile: confido in voi.

    Grazie anticipato per le risposte.
    Use the fork() Luke!

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Tutto dipende da dove hai messo le immagini e, di conseguenza, da come le punti.

    Partiamo dai concetti di base: getResource() e getResourceAsStream() funzionano esattamente come il ClassLoader. Ciò significa che il percorso che va dato alle immagini può essere assoluto o relativo.

    Un percorso assoluto inizia con lo slash ( / ) come primissimo carattere.
    Qualunque altro percorso è relativo.

    (quindi, nel codice da te postato, hai sempre fatto uso di percorsi relativi, poichè iniziano con il punto).

    Rimane da capire cosa si intende per percorso assoluto o relativo.

    Un percorso assoluto prende come "base di partenza", la "roor" del file JAR.
    Un percorso relativo prende come "base di partenza", la directory della classe da cui richiami getSource()/getResourceAsStream().

    Prendiamo il primo pezzo di codice del tuo esempio dove usi getResource():
    codice:
    System.out.println(getClass().getResource("./images/icona.png"));
    Questa riga di codice è eseguita dalla classe LocationJLabelTest che si trova nel package locationjlabeltest. La classe su cui richiami getResource() è quella data dal metodo "getClass()", ovvero, la classe stessa. Quindi quello è un percorso relativo a tale classe. Perchè l'immagine sia trovata, deve esistere una directory "locationjlabeltest" (il package), con all'interno una directory "images" con all'interno l'immagine "icona.png". Questa la struttura grafica del percorso:

    codice:
    ROOT del JAR
    +-- META-INF
    +-- +-- MANIFEST.MF
    +-- locationjlabeltest
    +-- +-- LocationJLabelTest.class
    +-- +-- images
    +-- +-- +-- icona.png
    ...
    Se non è così, l'immagine non viene trovata/caricata/visualizzata.

    Se, come penso di aver intuito, la tua struttura è questa qui sotto (nota la differenza!):
    codice:
    ROOT del JAR
    +-- META-INF
    +-- +-- MANIFEST.MF
    +-- images
    +-- +-- icona.png
    +-- +-- ...
    +-- locationjlabeltest
    +-- +-- LocationJLabelTest.class
    ...
    allora, la sintassi corretta da usare è la seguente (nota la differenza!):
    codice:
    System.out.println(getClass().getResource("/images/icona.png"));
    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16
    Ciao lele,
    per mia fortuna sapevo del fatto che la root directory per il jar è il jar stesso (o meglio la struttura interna), infatti la mia struttura del jar file è come nel primo caso: aprendolo con un decompressore noto che la struttura ricalca fedelmente quanto hai scritto tu.
    codice:
    ROOT del JAR
    +-- META-INF
    +-- +-- MANIFEST.MF
    +-- locationjlabeltest
    +-- +-- LocationJLabelTest.class
    +-- +-- images
    +-- +-- +-- icona.png
    Per testare la cosa ho impostato il percorso assoluto ed infatti è andato tutto liscio:
    codice:
    JLabel a=new JLabel(new ImageIcon(getClass().getResource("/locationjlabeltest/images/icona.png")));
    Tuttavia tale percorso coincide esattamente al path relativo (per sicurezza, come un fesso, mi sono pure fatto stampare i percorsi, ed è così), infatti se la struttura fosse come hai ipotizzato avrei dovuto usare il doppio punto (../) per risalire di un livello (giustamente su questo concordiamo).

    Siccome mi piacerebbe usare i percorsi relativi ti chiedo se hai lumi in merito, visto che a me la cosa sembra strana (sono su win quindi potrebbe pure essere normale )

    grazie in anticipo
    Use the fork() Luke!

  4. #4
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Semplicemente, non usare i punti.
    E' un cavillo sul quale mi imbatto spesso pure io, ci perdo le ore e poi mi ravvedo.


    codice:
    System.out.println(getClass().getResource("images/icona.png"));
    Il punto viene visto come il nome di una directory, quindi il loader si aspetta che, allo stesso livello della classe, esista una directory chiamata ".", con all'interno una directory chiamata "images", con all'interno il file immagine.

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  5. #5
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16
    Ma queste so cose assurde!
    Era davvero molto semplice eppure la hanno complicata sta cosa.... bah

    Un'ultima domanda: per il db dovrebbe essere lo stesso eppure non riesco: uso sqlite e funziona bene se prendo il jar creato con clean & bluid e ci affianco la cartella contenente il db.
    Il mio attuale codice è il seguente:
    codice:
    String dirverName="org.sqlite.JDBC"; 
    
    //------>Quello che servirebbe per il fat jar
    // String dbPath = getClass().getResource("db/optionals.sqlite").getFile();
    // String url="jdbc:sqlite:"+dbPath;
    
    //------>attuale funzionamento (ho tolto pure il punto e messo il path assoluto ma nulla nel fat jar
    String url="jdbc:sqlite:./db/optionals.sqlite";
    La cartella del db è "sorella" a quella delle immagini (che va alla grande)

    L'errore è l'sqlException, aggiungo il codice che segue questo di sopra:
    codice:
            try{
                Class.forName(dirverName);
                conn = DriverManager.getConnection(url);            
            }
            catch (SQLException ex){
                JOptionPane.showMessageDialog(null, "Errore di connessione al db nel costruttore!", "Attenzione!", JOptionPane.ERROR_MESSAGE);
                System.out.println("Errore di sqlException!");
            }
            catch (ClassNotFoundException ex){
                JOptionPane.showMessageDialog(null, "Errore: classe non trovata!", "Attenzione!", JOptionPane.ERROR_MESSAGE);
                System.out.println("Errore di Class not found!");            
            }
    Grazie ancora

    Se risolvo ti devo una birra LeleFT
    Use the fork() Luke!

  6. #6
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Due considerazioni:

    1) Non ammazzare le eccezioni, ma stampane sempre lo stackTrace: "Errore di sqlException!" non ha alcun significato, nemmeno per chi sviluppa. E' la descrizione vera dell'eccezione, con la causa e il punto in cui viene sollevata che sono utili a capire cosa è successo... e queste info te le dà lo StackTrace.

    2) Non credo abbia alcun senso (né credo sia fisicamente possibile) includere un DB dentro ad un Jar... un DB è qualcosa che "evolve" (record aggiunti/modificati). Un file JAR no, perchè non permette "scritture" (non in modo classico). Un file JAR è un archivio (ZIP) e, come tale, la scrittura consiste nell'eliminazione e re-introduzione di entry (ovvero, una modifica strutturale all'archivio, cosa diversa dalla scrittura di un file su disco).


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  7. #7
    Utente di HTML.it
    Registrato dal
    Jan 2013
    Messaggi
    16
    Rispondo solo ora per ringraziarti per la dritta perchè solo ora torno a lavorarci su causa forza (virale) maggiore

    Alla fine pretendevo pure troppo visto che tutti i maggiori programmi che si appoggiano a db hanno il file esterno.
    Use the fork() Luke!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.