Préchargement d'image

Résolu
Nitruk Messages postés 128 Date d'inscription lundi 8 août 2005 Statut Membre Dernière intervention 20 juillet 2009 - 26 août 2008 à 23:14
Nitruk Messages postés 128 Date d'inscription lundi 8 août 2005 Statut Membre Dernière intervention 20 juillet 2009 - 27 août 2008 à 18:38
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

Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
27 août 2008 à 16:32
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
3
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
26 août 2008 à 23:58
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
0
Nitruk Messages postés 128 Date d'inscription lundi 8 août 2005 Statut Membre Dernière intervention 20 juillet 2009
27 août 2008 à 14:38
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
0
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
27 août 2008 à 14:48
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
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Nitruk Messages postés 128 Date d'inscription lundi 8 août 2005 Statut Membre Dernière intervention 20 juillet 2009
27 août 2008 à 14:54
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
0
Twinuts Messages postés 5375 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 14 juin 2023 111
27 août 2008 à 15:21
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
0
Nitruk Messages postés 128 Date d'inscription lundi 8 août 2005 Statut Membre Dernière intervention 20 juillet 2009
27 août 2008 à 15:53
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
0
Nitruk Messages postés 128 Date d'inscription lundi 8 août 2005 Statut Membre Dernière intervention 20 juillet 2009
27 août 2008 à 16:07
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
0
Nitruk Messages postés 128 Date d'inscription lundi 8 août 2005 Statut Membre Dernière intervention 20 juillet 2009
27 août 2008 à 16:46
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
0
Nitruk Messages postés 128 Date d'inscription lundi 8 août 2005 Statut Membre Dernière intervention 20 juillet 2009
27 août 2008 à 18:38
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
0
Rejoignez-nous