IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

AWT/Swing Java Discussion :

[Swing] Problème avec getGraphics() et drawImage()


Sujet :

AWT/Swing Java

  1. #1
    Membre régulier
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Points : 80
    Points
    80
    Par défaut [Swing] Problème avec getGraphics() et drawImage()
    Bonjour,

    Je vais essayer d'expliquer au mieux mon problème tout en ajoutant que la partie de code intéressante.

    Je développe un labyrinthe sur lequel je vais déplacer un personnage.
    Je souhaite représenter ce personnage par une image.

    Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
     
    public class Labyrinthe extends JPanel implements Runnable {
    private int numero;
    	private Monde monde;
    	private ParamsJeu paramsJeu;
     
    public void paintComponent(Graphics g) {
    		super.paintComponent(g);
    		monde.dessine(g);
    	}
     
    public void prepare() {
    		// niveau 1
    		if (paramsJeu.getNiveau() == 1) {
     
    		}
    		// niveau 2
    		else if (paramsJeu.getNiveau() == 2) {
    			// premier labyrinthe
    			if (numero == LABYRINTHE_1) {
    				this.requestFocus();
     
     
    				paramsJeu.getPerso1().dessine(getGraphics());
     
     
    				addKeyListener(new KeyAdapter() {
    					public void keyPressed(KeyEvent e) {
    						if (e.getKeyCode() == KeyEvent.VK_LEFT) {
    							paramsJeu.getPerso1().deplaceVers(monde, paramsJeu.getPerso1().getPosX(), paramsJeu.getPerso1().getPosY()-1*Monde.getTaillePixel());
    							paramsJeu.getPerso1().dessine(getGraphics());
    						} else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
    							paramsJeu.getPerso1().deplaceVers(monde, paramsJeu.getPerso1().getPosX(), paramsJeu.getPerso1().getPosY()+1*Monde.getTaillePixel());
    							paramsJeu.getPerso1().dessine(getGraphics());
    						} else if (e.getKeyCode() == KeyEvent.VK_UP) {
    							paramsJeu.getPerso1().deplaceVers(monde, paramsJeu.getPerso1().getPosX()-1*Monde.getTaillePixel(), paramsJeu.getPerso1().getPosY());
    							paramsJeu.getPerso1().dessine(getGraphics());
    						} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
    							paramsJeu.getPerso1().deplaceVers(monde, paramsJeu.getPerso1().getPosX()+1*Monde.getTaillePixel(), paramsJeu.getPerso1().getPosY());
    							paramsJeu.getPerso1().dessine(getGraphics());
    						}	
    					}
    				});
    			}
    			// deuxieme labyrinthe
    			else {
    				addMouseListener(new MouseAdapter() {
    					public void mousePressed(MouseEvent e) {
    						// TODO
    					}
    					public void mouseReleased(MouseEvent e) {
    						// TODO
    					}
    				});
    				addMouseMotionListener(new MouseMotionAdapter() {
    					public void mouseDragged(MouseEvent e) {
    						// TODO
    					}
    				});
    			}
    		}
    		// niveau 3
    		else {
     
    		}
    	}
     
    public class Personnage {
     
    	// coordonnees initiales du personnage
    	private static int initX = 19;
    	private static int initY = 6;
     
    	private String nom;
    	private int oldX;
    	private int oldY;
    	private int posX;
    	private int posY;
    	private Image image;
     
    	private Personnage() {
    		oldX = posX = initX * Monde.getTaillePixel();
    		oldY = posY = initY * Monde.getTaillePixel();
    	}
     
    	public Personnage(String nom, String fichierImage) {
    		this();
    		this.nom = nom;
    		this.image = Toolkit.getDefaultToolkit().getImage(fichierImage);
    	}
     
    	// dessine un carre blanc a l'ancienne position
    	// dessine l'image a la nouvelle position
    	public void dessine(Graphics g) {
    		g.setColor(Color.RED);
    		g.fillRect(oldY, oldX, Monde.getTaillePixel(), Monde.getTaillePixel());
    		g.drawImage(image, posY, posX, null);
    	}
     
    // newX, newY : coordonnees absolues (multipliees par getTaillePixel())
    	public void deplaceVers(Monde m, int newX, int newY) {
    		// les coordonnees reelles se referent aux indices de la matrice Monde
    		// si les nouvelles coordonnees chevauchent deux cases de taille getTaillePixel(), on teste la matrice sur la deuxieme case
    		int realX = newX % Monde.getTaillePixel() == 0 ? newX / Monde.getTaillePixel() : newX / Monde.getTaillePixel() + 1;
    		int realY = newY % Monde.getTaillePixel() == 0 ? newY / Monde.getTaillePixel() : newY / Monde.getTaillePixel() + 1;
     
    		if (realX >= 0 && realX < Monde.getNbL() && realY >= 0 && realY < Monde.getNbC()
    				&& !m.isMurAt(realX, realY)) {
    			oldX = posX;
    			oldY = posY;
    			posX = newX;
    			posY = newY;
    		}
    	}
     
    	public int getPosX() {
    		return posX;
    	}
     
    	public int getPosY() {
    		return posY;
    	}
    }
    Mon problème est que lors de l'appel dans prepare() de paramsJeu.getPerso1().dessine(getGraphics()); il m'affiche mon carré rouge (en fait il sera blanc par la suite pour effacer l'ancienne position avant le déplacement) mais ensuite n'affiche pas l'image.

    Je ne comprends donc pas pourquoi lors de l'affichage du perso à sa position initiale, seul le carré rouge s'affiche et n'est pas écrasé par l'image. Il faut que je commence à déplacer mon perso avec les touches pour que l'image s'affiche à la place du carré rouge.

    Merci d'avance pour vos réponses.

  2. #2
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Parce qu'une Image chargee par Toolkit n'est pas forcement completement chargee apres retour de l'appel. Tu te retrouves donc dans la methode de dessin avec une image qui n'est pas complete. Le dernier parametre de drawImage(), l'ImageObserver, permet de recevoir une notification lorsque l'image est prete.

    La solution la plus simple ? Remplace ta ligne this.image = Toolkit... par this.image = ImageIO.read(...). ImageIO retourne toujours une image entierement chargee.

    Ah et pis paramsJeu.getPerso1().dessine(getGraphics()) c'est mal. Il faut eviter les appels a getGraphics(). Essaye plutot de faire un appel repaint() (ou repaint(x, y, w, h) pour ne redessiner qu'une partie de l'ecran) et mets tout ton code de dessin dans le paintComponent().
    Romain Guy
    Android - Mon livre - Mon blog

  3. #3
    Membre régulier
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Points : 80
    Points
    80
    Par défaut
    Citation Envoyé par Gfx
    Parce qu'une Image chargee par Toolkit n'est pas forcement completement chargee apres retour de l'appel. Tu te retrouves donc dans la methode de dessin avec une image qui n'est pas complete. Le dernier parametre de drawImage(), l'ImageObserver, permet de recevoir une notification lorsque l'image est prete.

    La solution la plus simple ? Remplace ta ligne this.image = Toolkit... par this.image = ImageIO.read(...). ImageIO retourne toujours une image entierement chargee.

    Ah et pis paramsJeu.getPerso1().dessine(getGraphics()) c'est mal. Il faut eviter les appels a getGraphics(). Essaye plutot de faire un appel repaint() (ou repaint(x, y, w, h) pour ne redessiner qu'une partie de l'ecran) et mets tout ton code de dessin dans le paintComponent().
    Merci pour ton message.
    Je ne comprends pas bien l'intérêt de la lecture d'image avec Toolkit si elle ne s'affiche pas compètement... J'avais essayé de passer en paramètre le panel dans lequel elle est sensée s'afficher en tant qu'ImageObserver, mais rien ne se passait non plus.

    J'ai essayé avec ImageIO.read(), et le problème est résolu. Merci!
    Une fois de plus, je ne vois vraiment pas l'intérêt d'utiliser la méthode getImage() de Toolkit.

    Enfin, tu m'as dit d'utiliser repaint(x, y, w, h) et de tout placer dans paintComponent mais le problème est que je souhaite dessiner cette fameuse image après que j'ai appuyé sur un bouton et non dès l'affichage de mon panel.

  4. #4
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Eh bien adapte ton code paint() pour qu'il ne dessine que quand le moment est venu.

    getImage() est tres interessant pour charger de grandes images sans empecher l'application de demarrer. C'etait aussi extremement utile dans les premieres versions de Java qui etaient beaucoup plus lentes. Generalement on charge plusieurs images avec getImage() et on attend leur chargement avec un MediaTracker.
    Romain Guy
    Android - Mon livre - Mon blog

  5. #5
    Membre régulier
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Points : 80
    Points
    80
    Par défaut
    D'accord, j'en vois mieux l'intérêt.

    J'ai adapté le code de paint() comme tu me l'as dit mais j'ai toujours un petit problème... Si la fenêtre de mon application passe en arrière plan et que je clique à nouveau sur ma fenêtre pour la faire apparaitre, le labyrinthe est là, mais mon personnage a disparu.

    Je suppose que cela a un rapport avec update().

  6. #6
    Gfx
    Gfx est déconnecté
    Expert éminent
    Avatar de Gfx
    Inscrit en
    Mai 2005
    Messages
    1 770
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations forums :
    Inscription : Mai 2005
    Messages : 1 770
    Points : 8 178
    Points
    8 178
    Par défaut
    Non. C'est pour ca que je te dis de mettre TOUT le code de dessin dans paintComponent(), nulle part ailleurs.
    Romain Guy
    Android - Mon livre - Mon blog

  7. #7
    Membre régulier
    Inscrit en
    Novembre 2003
    Messages
    142
    Détails du profil
    Informations forums :
    Inscription : Novembre 2003
    Messages : 142
    Points : 80
    Points
    80
    Par défaut
    Je te remercie pour tes conseils. Dorénavant, je n'oublierais plus de TOUT mettre dans la méthode paintComponent().

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [SWING]Problème avec l'ActionListener
    Par Goupo dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 07/06/2007, 01h36
  2. Swing : problème avec un Jbutton
    Par Gilouou dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 05/11/2006, 00h37
  3. [Swing] Problème avec les GridBagLayout
    Par CrazySeb dans le forum AWT/Swing
    Réponses: 1
    Dernier message: 28/04/2006, 14h47
  4. [SWING] Problème avec JInternalFrame et JDesktopPane
    Par rprom1 dans le forum AWT/Swing
    Réponses: 5
    Dernier message: 23/03/2006, 11h56
  5. [Swing] Problème avec un bean et un arraylist
    Par kikoufr dans le forum AWT/Swing
    Réponses: 16
    Dernier message: 30/09/2004, 09h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo