Préchargement d'image

Résolu
Signaler
Messages postés
128
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
20 juillet 2009
-
Messages postés
128
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
20 juillet 2009
-
Bonjour, j'ai aujourd'hui une vraie question de vrai débutant à poser :

Y  a-t-il un moyen de précharcher une image, et de ne rendre la main au programme qu'une fois que c'est fait ? Car j'utilise des panneaux dont la méthode paintComponant affiche une petite image, dont l'objet correspondant a été créé dans le constructeur.
Or ces images ont tendance (environ une fois sur deux) à ne pas toutes apparaître à l'apparition de la fenêtre, mais à le faire si je la rabats et l'aggrandis (repaint, avec l'intervalle pour finir de charger). J'ai cru comprendre que le constructeur de ImageIcon chargeait complètement avant d erendre la main et que le getImage d eToolkit chargeait en arrière plan, avant de comprende l'inverse. En tout cas, j'ai tuilisé ces 2 méthodes sans remarquer de différence, et j'ai même essayer de faire une boucle avec ImageIcon :

    icone = new ImageIcon(getClass().getClassLoader().getResource(add));
    for(int i = 1; icone.getImageLoadStatus() != MediaTracker.COMPLETE; i++)
      {
   System.out.println(Integer.toString(icone.getImageLoadStatus()));
   i--;
   }

Ma fenêtre n'apparaissait pas, et en ajoutant le println  j'ai compris que le LoadStatus restait bloqué à 2 et n'avançait pas tant que durait la boucle, qui je suppose ne devait pas laisser de temps pour charger l'image en arrière plan.
Un LoadStatus d e2 correspond à l'état ABORTED, or les images apparaissent bien avec un repaint() tardif (Pas la peine d'appeler repaint^après l'apparition de la fenêtre, c'est sans effet)

Nitruk

10 réponses

Messages postés
5366
Date d'inscription
dimanche 4 mai 2003
Statut
Modérateur
Dernière intervention
6 décembre 2021
111
Salut,

tu peux toujours essayer avec la méthode 'getResourceAsStream'
si non utiliser la classe ResourceLocator dispo ICI (2ème message)

bien que normalement tu ne devrais pas avoir de problèmes (je n'ai pas le même problème en local avec une image dans le jar)...

------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
Messages postés
5366
Date d'inscription
dimanche 4 mai 2003
Statut
Modérateur
Dernière intervention
6 décembre 2021
111
Salut,

fait plutôt ça :

ImageIcon icon = new ImageIcon(...);
icon.getImage(); // pour t'assurer que l'image est bien chargée
//exploitation de l'objet ImageIcon

------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
Messages postés
128
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
20 juillet 2009

Merci, mais j'utilise déjà getImage(), étant de toute façon obligé d'employer un objet Image pour des fonctions comme
int, int, java.awt.image.ImageObserver) drawImage(Image img, int x, int y, ImageObserver observer)
Nitruk
Messages postés
5366
Date d'inscription
dimanche 4 mai 2003
Statut
Modérateur
Dernière intervention
6 décembre 2021
111
Salut,

oui mais faiT le une première fois avant de l'utiliser dans la méthode drawImage, comme ça tu n'attendras pas *ce* moment là pour charger complètement l'image.

------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
Messages postés
128
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
20 juillet 2009

Erci encore mais je viens de le faire et ça ne change rien, d'ailleurs  le chargement commence bien avant puisque ma boucle m'envoyait des 8
(COMPLETE) avant de bloquer sur des 2 (ABORTED).

Nitruk
Messages postés
5366
Date d'inscription
dimanche 4 mai 2003
Statut
Modérateur
Dernière intervention
6 décembre 2021
111
Salut,

oui mais la solution que je te propose ne doit pas avoir ta boucle ...

tien voici 3 exemples pour charger un image (exemple pour un SplashScreen) :

exemple 1 : Utilisation de ImageIcon et la méthode getImage
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Test extends JFrame {
   
    public Test() {
        setDefaultCloseOperation(3);
       
        //chargement de l'image
        ImageIcon icon = new ImageIcon("img.png");
        icon.getImage();
        // creation d'un label pour l'image
        JLabel content = new JLabel();
        content.setIcon(icon);
        //ajout du label à la fenetre
        setContentPane(content);

        pack();
        setLocationRelativeTo(null);
    }
   
    public static void main(String[] args) {
        new Test().setVisible(true);
    }

}

exemple 2 : Utilisation de ImageIcon et de la méthode read de l'objet ImageIO
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Test extends JFrame {
   
    public Test() {
        setDefaultCloseOperation(3);
       
        //chargement de l'image
        BufferedImage img = null;
        try {
            img = ImageIO.read(new File("img.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        ImageIcon icon = new ImageIcon(img);
        icon.getImage();
        // creation d'un label pour l'image
        JLabel content = new JLabel();
        content.setIcon(icon);
        //ajout du label à la fenetre
        setContentPane(content);

        pack();
        setLocationRelativeTo(null);
    }
   
    public static void main(String[] args) {
        new Test().setVisible(true);
    }

}

exemple 3 : Utilisation de Image et d'un MediaTracker

import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Test extends JFrame {
   
    public Test() {
        setDefaultCloseOperation(3);
       
        //chargement de l'image
        Image img = Toolkit.getDefaultToolkit().createImage("img.png");
        MediaTracker mt = new MediaTracker(this);
        mt.addImage(img, 0);
        try {
            mt.waitForAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
       
        // creation d'un label pour l'image
        JLabel content = new JLabel();
        content.setIcon(new ImageIcon(img));
        //ajout du label à la fenetre
        setContentPane(content);

        pack();
        setLocationRelativeTo(null);
    }
   
    public static void main(String[] args) {
        new Test().setVisible(true);
    }

}

------------------------------------
"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
Messages postés
128
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
20 juillet 2009

La première solution est celle que j'utilisais jusque là, la deuxième fonctionne sans problème, sauf que je ne peux pas utiliser getClass().getClassLoader().getResource(add) (La méthode toString() me renvoie une adresse absolue de type file:/d:/Java/image.gif qui déclenche cette erreur quand elle est soumise au constructeur de File  :

javax.imageio.IIOException: Can't read input file!
        at javax.imageio.ImageIO.read(ImageIO.java:1275)
        at clientFen$1PanneauIcone.(clientFen.java:273
        at clientFen.(clientFen.java:311)
        at Client.main(Client.java:16)
Exception in thread "main" java.lang.NullPointerException
        at javax.swing.ImageIcon.(ImageIcon.java:161)
        at clientFen$1PanneauIcone.(clientFen.java:277
        at clientFen.(clientFen.java:311)
        at Client.main(Client.java:16)

Or mon programme prenant place dans un jar, j'ai besoin d'ne apsser par là. Je vais donc essayer la 3ème solution de ce pas.

Nitruk
Messages postés
128
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
20 juillet 2009

Je suis encore passé à deux doigts d'y arriver : Si le constructeur de File n'accepte aps ce type d'adresses, celui d'URI s'en accomode très bien, et on peut construire un File à partir d'un URI.
... Sauf que dans un jar, ma classe se met à émettre une erreur :

Exception in thread "main" java.lang.IllegalArgumentException: URI is not hierarchical
        at java.io.File.(File.java:363)
        at clientFen$1PanneauIcone.(clientFen.java:272)
        at clientFen.(clientFen.java:331)
        at Client.main(Client.java:16)

Nitruk
Messages postés
128
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
20 juillet 2009

La 3ème solution donne le même résultat que la première, ce qui n'est aps surprenant, puisque le constructeur d'ImageIcon utilise le Media Tracker, donc en théorie devrait attendre d'avoir fini de charger l'image avant de rendre la main.
Je conclus donc à un bug du tracker, ce qui m'avance bien, avec URI qui ne fonctionne pas dans un jar..
Si quelqu'un a une meilleure idée, je serais ravi de l'entendre.
Merci d'avance

Nitruk
Messages postés
128
Date d'inscription
lundi 8 août 2005
Statut
Membre
Dernière intervention
20 juillet 2009

Merci, cette fois ça marche. Apparement (d'après cette expérience et ce que j'ai pu voir sur les forums de Sun) mon problème serait lié à l'utilisation de fichiers dans un jar (Les fichiers temporaires doivent être créés dans le répertoire de la classe, et on ne peut pas directement créer un fichier dans un jar). Avec le getResourceasStream() j'ai les avantages de ImageIO.read()
 (mes images sont entièrement chargées avant l'apparition de la fenêtre) sans les inconvénients de File(URI) (Ca fonctionne dans un jar.)

Donc tout va bien, et merci encore !

Nitruk