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 :

repaint() non appelé mais paintComponent(g) oui


Sujet :

AWT/Swing Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre actif
    Profil pro
    Étudiant
    Inscrit en
    Août 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2013
    Messages : 13
    Par défaut repaint() non appelé mais paintComponent(g) oui
    Bonjour à tous,
    Cela fait un bon moment que je suis coincé sur un shoot'em up.Peut-être pourriez vous me donner un coup de main.
    La méthode de paintComponent de Joueur n'est pas appelé par repaint().
    Console :
    vaisseau:10ms CAS 1
    vaisseau:10ms CAS 2
    vaisseau:10ms CAS 3


    Voila un bout de 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
    public class Terrain extends JPanel {
    	...
    	private void initComponents() {
    		setLayout(null);
    		...
    		timerJ_ = new Timer(10, new DeplacerJoueur(this));
    	}
    	@Override
    	public void paintComponent(Graphics g) {
    		super.paintComponent(g);
    		Graphics2D g2d = (Graphics2D) g;
    		g2d.drawString(joueur_.getArme() + "    Vies: " + nbVies_
    				+ "    Score: " + score_, 480, 30);
    		// Toolkit.getDefaultToolkit().sync();g.dispose();
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class DeplacerJoueur implements ActionListener {
    	private Terrain t_;
    	public DeplacerJoueur(Terrain t) {
    		t_ = t;
    	}
    	@Override
    	public void actionPerformed(ActionEvent evt) { // tick de timer
    		System.out.println("vaisseau:10ms  CAS 1");
    		t_.getJoueur().deplacer();
    		System.out.println("vaisseau:10ms  CAS 2");
    		t_.getJoueur().repaint();
    		System.out.println("vaisseau:10ms  CAS 3");
    	}
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Joueur extends Vaisseau {// Vaisseau herite de JComponent)
    	@Override
    	public void paintComponent(Graphics g) {
    		super.paintComponent(g);
    		System.out.println("repaint fonctionne");
    		Graphics2D g2d = (Graphics2D) g;
    		setVisible(true);
    		setPreferredSize(new Dimension(50, 19));
    		g2d.drawImage(img_, (int) hg_.getX(), (int) hg_.getY(), this);
    		g2d.setColor(Color.blue);
    	}
    }
    A la base, j'affichais tout dans paint() de Terrain mais j'ai remplacé par paintComponent() dans chaque objet affiché.
    Juste pour tester, lorsque dans le paintComponent de Terrain je met joueur_.repaint() ca n'entre pas dans la méthode.
    Cependant joueur_.paintComponent(g) fonctionne (meme si ce n'est pas recommandé et que c'est dans DeplacerJoueur que je veut le mettre).
    Je me dit que peut-être paintComponent ne sait pas où se dessiner et paintComponent fonctionne grâce au parametre g ?

    Qu'en dîtes-vous ? Merci

  2. #2
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    La méthode "getJoueur" de "Terrain" renvoie quoi ?
    J'ai du mal à comprendre la hiérarchie de tes objets d'affichage.
    Si ce n'est pas déjà le cas, je t'encourage vivement à passer par une BufferedImage. Tu modifies le graphique de cette image comme tu le souhaites.
    C'est uniquement cette image qui sera affichée, rien d'autre. Elle sera affichée par un unique JPanel toutes les X ms. Tu n'as qu'une seule méthode paintComponent à modifier dans un seul JPanel pour afficher l'image. Le "repaint" sera appeler uniquement sur le seul JPanel qui s'occupe de l'affichage.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  3. #3
    Membre actif
    Profil pro
    Étudiant
    Inscrit en
    Août 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2013
    Messages : 13
    Par défaut Explications
    Salut et merci d'avoir répondu.
    Pour l'instant dans Terrain, j'ai 3 timers gérant la vitesse pour:
    Déplacer un ennemi
    Déplacer le joueur
    Déplacer les tirs joueur

    Le probleme est le même pour chacun des timers.
    Chaque tick de timer permet de déplacer a une vitesse différentes puis d'afficher chacun par son paintComponent() respectif.

    getJoueur() est une méthode de Terrain qui renvoie le joueur instancié dans la classe.
    J'ai vais utiliser le BufferedImage comme tu me le conseilles mais le repaint() n'est pas appelé même si je ne laisse que le System.out.println().

    Voici un peu plus de 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
    public class Terrain extends JPanel {
    	public Terrain(int LARG_ECRAN, int HAUT_ECRAN) {
    		setPreferredSize(new Dimension(LARG_ECRAN, HAUT_ECRAN));
    		initComponents(); // Initialisation des composants
    	}
    	private void initComponents() {
    		setLayout(null);
    		setBorder(BorderFactory.createLineBorder(Color.blue));
    		setBackground(Color.black);
    		score_ = 0;
    		nbVies_ = 3;
    		joueur_ = new Joueur();
    		add(joueur_);
    		ennemis_ = new ArrayList<Ennemi>();// Initialisation liste ennemis
    		tirsEn_ = new ArrayList<Tir>(); // Initialisation liste tirs ennemis
    		ennemi_ = new Ennemi0();
    		ennemis_.add(ennemi_); // Ajout liste ennemis
    		tirsEn_.add(ennemi_.getTir());
    		addKeyListener(new TAdapter());
    		setFocusable(true);
    		timerEn_ = new Timer(8, new DeplacerEnnemis(this));
    		timerJ_ = new Timer(10, new DeplacerJoueur(this));
    		timerTirJ_ = new Timer(1, new DeplacerTirJoueur(this));
    		timerEn_.setInitialDelay(1000); // pause d'une s
    		timerEn_.start();
    		timerJ_.start();
    		timerTirJ_.start();
    	}
    }
    J'ai 2 questions:
    1)Est-il possible d'appeler la méthode repaint() d'une classe héritant de JComponent depuis n'importe ou ? (ici depuis un actionListener).
    2)Saura-t-il ou le dessiner ?

  4. #4
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Il ne faut pas confondre les timers pour effectuer les calculs et le timer unique qui va appeler régulièrement le rafraichissement graphique.
    Pour répondre à tes questions :
    1. repaint peut être appelé de n'importe où dans une classe héritant de JComponent
    2. La méthode "repaint" poste une demande de rafraichissement dans la liste de travail du thread EDT. Il n'est pas possible de savoir quand le thread va faire le rafraichissement, mais il le fera. Et il passera par la méthode "paintComponant" pour rafraichir le composant.

    Voici un exemple rapide que j'avais poster pour une autre question il y a quelques jours. Je l'ai modifié pour proposer une solution à ton problème. Un clic sur une case modifie une image. Un thread se charge de demander un rafraichissement toutes les 0.1s, indépendamment des modifications effectuées. L'image est affichée via la méthode "paintComponant" :
    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
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.image.BufferedImage;
     
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
     
    public class CasseTete extends JComponent implements MouseListener
    {
    	private static final long serialVersionUID = 1L;
    	private BufferedImage image;
    	private Graphics2D graph;
    	private boolean[][] tab = new boolean[ 5 ][ 5 ];
     
    	public static void main( String arg[] )
    	{
    		new CasseTete();
    	}
     
    	public CasseTete()
    	{
    		image = new BufferedImage( 400, 300, BufferedImage.TYPE_INT_ARGB );
    		graph = image.createGraphics();
     
    		for( int i = 0 ; i < 5 ; ++i )
    		{
    			for( int j = 0 ; j < 5 ; ++j ) { tab[ i ][ j ] = false; }
    		}
     
    		ecrire_image();
    		addMouseListener( this );
    		setPreferredSize( new Dimension( image.getWidth(), image.getHeight() ) );
     
    		JFrame frame = new JFrame();
    		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    		frame.getContentPane().add( this );
    		frame.pack();
    		frame.setVisible( true );
     
    		new Thread( new Runnable()
    		{
    			@Override
    			public void run()
    			{
    				while( true )
    				{
    					repaint();
    					try{ Thread.sleep( 100 ); } catch( Exception exc ){}
    				}
    			}
    		}
    		).start();
    	}
     
    	private void ecrire_image()
    	{
    		int largeur = image.getWidth();
    		int hauteur = image.getHeight();
     
    		for( int i = 0 ; i < 5 ; ++i )
    		{
    			for( int j = 0 ; j < 5 ; ++j )
    			{
    				if( tab[ i ][ j ] ) { graph.setColor( Color.WHITE ); }
    				else { graph.setColor( Color.BLACK ); }
    				graph.fillRect( i * largeur / 5, j * hauteur / 5, largeur / 5, hauteur / 5 );
    			}
    		}
     
    		graph.setColor( Color.RED );
    		for( int i = 0 ; i < image.getWidth() ; i += image.getWidth() / 5 ) { graph.fillRect( i - 2, 0, 4, image.getHeight() ); }
    		for( int i = 0 ; i < image.getHeight() ; i += image.getHeight() / 5 ) { graph.fillRect( 0, i - 2, image.getWidth(), 4 ); }
    	}
     
    	@Override
    	protected void paintComponent( Graphics g )
    	{
    		super.paintComponent( g );
    		g.drawImage( image, 0, 0, this );
    	}
     
    	@Override
    	public void mouseClicked( MouseEvent event )
    	{
    		if( event.getX() < image.getWidth() && event.getY() < image.getHeight() )
    		{
    			int x = event.getX() / ( image.getWidth() / 5 );
    			int y = event.getY() / ( image.getHeight() / 5 );
    			tab[ x ][ y ] = !tab[ x ][ y ];
    			new Thread( new Runnable()
    			{
    				@Override
    				public void run()
    				{
    					ecrire_image();
    				}
    			} ).start();
    		}
    	}
     
    	@Override
    	public void mouseEntered( MouseEvent arg0 ){}
    	@Override
    	public void mouseExited( MouseEvent arg0 ){}
    	@Override
    	public void mousePressed( MouseEvent arg0 ){}
    	@Override
    	public void mouseReleased( MouseEvent arg0 ){}
    }
    C'est une solution très simpliste. Pour éviter d'afficher une image à moitié modifiée, tu peux imaginer travailler avec 2 images. Une image qui est affichée et une image qui est modifiée. Lorsque la modification est terminée, tu échanges les deux images.
    Pour le double buffering, il y a des solutions plus robustes dans la FAQ et les tutoriaux.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  5. #5
    Membre actif
    Profil pro
    Étudiant
    Inscrit en
    Août 2013
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2013
    Messages : 13
    Par défaut merci...
    Merci pour le code et ton aide et désolé du retard (j'ai été obligé de m'absenter).

    Je n'avais pas pensé à utiliser un timer pour rafraîchir l'image indépendamment des modifications. La méthode qui est de redessiner tout le panel et en utilisant la méthode drawImage() d'une BufferedImage fonctionne bien, j'ai testé.
    C'est la méthode que j'utilise à présent.

    Concernant les panels spécifiquement: je n'ai jamais vraiment compris comment fonctionne la mise a jour d'un panel ajouté dans un autre. J'ai eu beau faire des recherche, tout cela fonctionne en statique mais des qu'il y a un changement et que je veux utiliser repaint() ca bloque.

  6. #6
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Par défaut
    Citation Envoyé par leoenfolie44 Voir le message
    Concernant les panels spécifiquement: je n'ai jamais vraiment compris comment fonctionne la mise a jour d'un panel ajouté dans un autre. J'ai eu beau faire des recherche, tout cela fonctionne en statique mais des qu'il y a un changement et que je veux utiliser repaint() ca bloque.
    Je serais intéressé par un exemple très simple reproduisant ce "blocage".
    Techniquement, il n'y a rien de spécial : il suffit d'appeler "repaint" sur l'instance du JPanel.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

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

Discussions similaires

  1. Click() sur une img, id non reconnue, mais class oui
    Par miclebowski dans le forum jQuery
    Réponses: 0
    Dernier message: 20/06/2010, 16h26
  2. classe Action non appelée
    Par jc44 dans le forum Struts 1
    Réponses: 4
    Dernier message: 18/08/2006, 15h22
  3. onkeyup non appellé
    Par GregPeck dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 23/02/2006, 18h22
  4. Verifier formulaire - fonction non appelée
    Par nerick dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 08/12/2005, 18h44
  5. Réponses: 3
    Dernier message: 23/08/2005, 12h02

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