Afficher différentes images dans un jpanel

Résolu/Fermé
drakahon Messages postés 9 Date d'inscription lundi 22 avril 2013 Statut Membre Dernière intervention 24 avril 2013 - 22 avril 2013 à 17:50
drakahon Messages postés 9 Date d'inscription lundi 22 avril 2013 Statut Membre Dernière intervention 24 avril 2013 - 23 avril 2013 à 11:40
Bonjour,
Mon soucis c'est que j'aimerai ajouter des images à la position du clique de la souris. Donc pour l'instant, si je prend qu'une seule image, tout fonctionne. Mais des que j'ajoute une image différente de la première, c'est la dernière image qui s'affiche là où j'ai poser toutes mes images. J'utilise paintComponent et repaint.

Voilà je suis dans l'impasse depuis plusieurs jour, si vous pouviez m'aider ca serait gentil :)
Merci.

8 réponses

KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022 2 985
22 avril 2013 à 18:33
Il faudrait voir ton code, mais vu la description de ton problème tu utilises très certainement plusieurs fois la même variable pour stocker plusieurs images différentes. Il faut que tu sauvegardes toutes tes images et leur positions respectives dans une liste au fur et à mesure que tu les ajoutes avec ton clic de souris, puis que dans ton paintComponent tu lises toute ta liste pour afficher tes différentes images et leur position.
0
drakahon Messages postés 9 Date d'inscription lundi 22 avril 2013 Statut Membre Dernière intervention 24 avril 2013
22 avril 2013 à 18:53
Tout d'abbord merci de m'avoir répondu, j'ai voulu faire quelque test justement mais sans succes... Je vous montre une partie du code parce que sinon ca serait trop grand...

lorsque je rajoute l'image sur le panel :


public void mousePressed(MouseEvent evt) {
            compt = 0;
            positionImPan = 0;
            modifImPan = 0;
            Xclic = evt.getX();
            Yclic = evt.getY();
            Iterator iterCoordX = (((Room) selectedRessource[4]).getCoordX()).iterator(); //on parcours les coordX deja enregistré
            Iterator iterCoordY = (((Room) selectedRessource[4]).getCoordY()).iterator(); // on parcours les coordY deja enregistré
            Iterator iterObj = (((Room) selectedRessource[4]).getListObj()).iterator(); //on parcours les objects deja enregistré
            Iterator iterImPan = imPan.iterator();  //on parcours les images poser sur la panel 

            while (iterCoordX.hasNext() && iterCoordY.hasNext() && iterObj.hasNext() && iterImPan.hasNext() && modifImPan != 1) {

                int x = (Integer) iterCoordX.next();
                int y = (Integer) iterCoordY.next();
                ob = (Objects) iterObj.next();
                int idSprit = ob.getSpriteID();
                Sprite sprite = ((Sprite) rcArray[0].getRessource(idSprit));
                int hauteur = sprite.getImageHeight();
                int largeur = sprite.getImageWidth();
                imP = (ImagePanel2) iterImPan.next();
                //on cherche a savoir si on a selectionné une image
                if (Xclic > (x - (largeur / 2)) && Xclic < (x + (largeur / 2)) && Yclic > (y - (hauteur / 2)) && Yclic < (y + (hauteur / 2))) {
                    jRoomPanel.remove(imP);
                    path = sprite.getImagePath();
                    modifImPan = 1;
                } else {
                    positionImPan++;
                }
            }
            cheminR.add(path); //on enregistre le chemin dans une liste
            File file = new File(path);

            imP = new ImagePanel2(file); //imP est de type ImagePanel2, il est déclarer au début du programme      

            imP.setSize(img.getWidth(), img.getHeight());
            jRoomPanel.add(imP);


            jRoomPanel.repaint();
            jRoomYTextField.setText(String.valueOf(Yclic));
            jRoomXTextField.setText(String.valueOf(Xclic));


        }


et voici la classe ImagePanel2 :



 public class ImagePanel2 extends JPanel {    // une classe de panel avec image            

        public ImagePanel2(File fileImg) {
            super();
            try {
                img = ImageIO.read(fileImg); //img est de type BufferedImage déclarer au début
                longX = img.getHeight();
                largY = img.getWidth();
            } catch (IOException e) {
                img = null;
                System.err.print("Fichier image invalide");
            }
            int hauteur = img.getHeight();
            int largeur = img.getWidth();
            xCoordObj = Xclic - sp.getImageCenterX();
            yCoordObj = Yclic - sp.getImageCenterY();
            setBounds(xCoordObj, yCoordObj, largeur, hauteur);
            setVisible(true);
        }

        public void paintComponent(Graphics g) {
           
           super.paintComponent(g);
            File f= new File(cheminR.get(compt));
            try {
                BufferedImage temp=ImageIO.read(f);
                g.drawImage(temp, 0, 0, temp.getWidth(), temp.getHeight(), null);


            } catch (IOException ex) {
                Logger.getLogger(JFrame.class.getName()).log(Level.SEVERE, null, ex);
            }
           compt++;
        }
    }





Désolé du gros pavé, en tout cas merci encore de m'aider :)
0
KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022 2 985
22 avril 2013 à 19:32
Tout ceci me parait bien compliqué !

Si j'ai bien compris, ton test de mousePressed consiste à tester si l'endroit où tu as cliqué correspond à une image que tu affiches. Or ces images sont des ImagePanel2, donc il serait plus simple d'ajouter des MouseListener à chacun de tes JPanel plutôt que de faire un contrôle centralisé comme tu l'as fait.

Ensuite tu fais sans cesse des appels au fichier, en particulier dans ton paintComponent, cela va énormément ralentir ton programme, parce que la méthode paintComponent va être automatiquement appelée par le programme par exemple lorsque tu vas déplacer ta fenêtre. Si par exemple tu déplaces ta fenêtre de 100px, il est potentiellement possible de faire 100 appels à paintComponent, qui vont donc à chaque fois charger les fichiers pour chaque image... Et pire : toutes les images chargées depuis le lancement du programme vont être conservées en mémoire, ce qui représente une énorme quantité de mémoire perdue pour rien !

Enfin pour revenir à ta question, tu affiches toutes tes images de la même manière, en lisant le fichier cheminR.get(compt), or ce compt qui est initialisé au mouseClicked à 0 est incrémenté à chaque paintComponent, mais ce n'est pas du tout comme cela que fonctionne les repaint, ne serait-ce que parce que cette méthode peut-être appelée automatiquement (et que dans ce cas la variable compt n'aura pas été initialisée !)

Alors, difficile de tout corriger mais tu dois pouvoir simplifier énormément de chose, aussi bien au niveau du code, qu'au niveau de la logique du programme (économie en temps, en mémoires, etc.)

Voici une base pour ImagePanel2 :

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;

import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class ImagePanel2 extends JPanel implements MouseListener
{
    // extends JPanel
    /////////////////
    
    private final Image img;

    public ImagePanel2(String fileName)
    {
        img = new ImageIcon(fileName).getImage();
        setSize(img.getWidth(this),img.getHeight(this));
        
        addMouseListener(this);
    }
    
    public void paintComponent(Graphics g) 
    {
        super.paintComponent(g);
        g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
    }

    // implements MouseListener
    ///////////////////////////

    private static int ids = 0;
    private final int id = ids++;
        
    public void mousePressed(MouseEvent evt)
    {
        System.out.println("Image "+id+" clic on "+evt.getPoint());
    }
    
    public void mouseClicked(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}
0
drakahon Messages postés 9 Date d'inscription lundi 22 avril 2013 Statut Membre Dernière intervention 24 avril 2013
22 avril 2013 à 20:03
" il serait plus simple d'ajouter des MouseListener à chacun de tes JPanel " je n'ai pas trop compris, il faudrait que je fasse un JPanel pour chaque image que j'ajoute ?

Sinon, oui au début j'avais redéfini paintComponent comme cet exemple, mais je pensais que mon soucis venait du fait que img garde le chemin de la dernière image et donc quand je faisais appel au repaint, il modifiait le chemin de toute les images précédentes.
0
KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022 2 985
22 avril 2013 à 20:26
"il faudrait que je fasse un JPanel pour chaque image que j'ajoute"
Bien sûr, ce serait tellement plus simple !

D'une part pour afficher tes images puisqu'il y aurait un repaintComponent par image, que tu n'aurais donc pas à gérer toi même, et donc sans avoir à te mélanger les pinceaux avec tes cheminR.get(compt) qui ne fonctionnent pas (rapport au compt qui est initialisé dans mousePressed et incrémenté dans repaintComponent alors que cette méthode peut-être appelé automatiquement et tout planter).

D'autre part tu pourrais tout de suite savoir sur quelle image tu cliques puisque ton évènement serait directement attaché à ton panel. Tu n'aurais donc pas à faire tes grosses boucles avec des Iterator tout moches pour savoir où tu cliques, gères cela directement dans ImagePanel2...
0

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

Posez votre question
drakahon Messages postés 9 Date d'inscription lundi 22 avril 2013 Statut Membre Dernière intervention 24 avril 2013
22 avril 2013 à 20:38
Mais est ce que je peux mettre tous ces JPanel dans un JPanel ? Si oui, alors je n'ai plus qu'à travailler avec des JPanel... ce qui serait peut être plus simple que ces itérators :)
0
KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022 2 985
22 avril 2013 à 20:53
Bien sûr qu'on peux mettre des JPanel dans d'autres JPanel c'est d'ailleurs leur rôle !

Remarque : vu ma version de la classe ImagePanel2, il est même possible de remplacer l'extends JPanel par autre chose, de plus simple, par exemple java.awt.Component.
Dans ce cas ce n'est pas paintComponent() qu'il faudra redéfinir mais paint()

Exemple complet (testes le clic sur les images tu verras que ça fonctionne)

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

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

public class ImageComponent extends Component implements MouseListener
{
    private static final long serialVersionUID = 1;

    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setLayout(null);        
        frame.setSize(500,500);
                
        ImageComponent img1 = new ImageComponent("C:/1.jpg");
        img1.setLocation(100, 100);
        frame.add(img1);
        
        ImageComponent img2 = new ImageComponent("C:/2.jpg");
        img2.setLocation(300, 100);
        frame.add(img2);
        
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    // extends JPanel
    /////////////////
    
    private final Image img;

    public ImageComponent(String fileName)
    {
        img = new ImageIcon(fileName).getImage();
        setSize(img.getWidth(this),img.getHeight(this));
        
        addMouseListener(this);
    }
    
    public void paint(Graphics g) 
    {
        super.paint(g);
        g.drawImage(img, 0, 0, getWidth(), getHeight(), null);
    }

    // implements MouseListener
    ///////////////////////////

    private static int ids = 0;
    private final int id = ids++;
        
    public void mousePressed(MouseEvent evt)
    {
        System.out.println("Image "+id+" clic on "+evt.getPoint());
    }
    
    public void mouseClicked(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}
0
drakahon Messages postés 9 Date d'inscription lundi 22 avril 2013 Statut Membre Dernière intervention 24 avril 2013
22 avril 2013 à 22:38
Je viens de tester, alors j'ai juste quelques questions, setLocation() c'est ce qui permet de positionner l'image dans la JFrame ? Aussi, est-ce que je peux l'adapter pour un JPanel ? Puisqu'en fait, ce qu'on veut faire, c'est une fenêtre qui contient un JPanel avec toutes les images donc c'est pour ca que je tenais à mettre mes images dans un JPanel.

Merci.
0
KX Messages postés 16643 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 6 décembre 2022 2 985
23 avril 2013 à 06:03
"ce qu'on veut faire, c'est une fenêtre qui contient un JPanel avec toutes les images"
Une JFrame contient déjà un JPanel (que l'on peut obtenir avec getContentPane) et c'est dans ce JPanel que sont ajoutés les images.

"setLocation() c'est ce qui permet de positionner l'image dans la JFrame ?"
setLocation permet de positionner l'image par rapport au container qui la contient (ici, c'est don le JPanel de la JFrame)

Ces trois codes reviennent donc au même :

frame.add(img1);

frame.getContentPane().add(img1);

JPanel panel = new JPanel();
panel.add(img1);
frame.setContentPane(panel);
0
drakahon Messages postés 9 Date d'inscription lundi 22 avril 2013 Statut Membre Dernière intervention 24 avril 2013
23 avril 2013 à 11:05
ok merci je vais changer mon code et voir si ca marche, je dirais ce qu'il en est :) Merci encore.
0
drakahon Messages postés 9 Date d'inscription lundi 22 avril 2013 Statut Membre Dernière intervention 24 avril 2013
23 avril 2013 à 11:40
Ca marche !! Merci beaucoup d'avoir pris le temps de m'expliquer et de régler mon soucis ! Bonne journée !
0