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

 Java Discussion :

Méthode getGraphics() qui renvoie null en Swing


Sujet :

Java

  1. #1
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Par défaut Méthode getGraphics() qui renvoie null en Swing
    Bonjour,
    je débute en java et je suis un tutorial avec des exercices corrigés. J'essaie par moi m^eme et quand je n'y arrive pas je regarde le corrigé. Jusque là, ça va !
    Mais là je bloque avec la méthode getGraphics dans un JPanel qui me ramène null. Dans le corrigé ça marche, mais dans mon programme c'est "null".
    J'ai regardé sur internet et j'ai vu qu'il vaut mieux surcharger paintComponent(Graphics g) mais pareil ça me ramène null. Je trouve le graphisme super difficile à manipuler en java pour l'instant.
    Je montre mon code, si quelqu'un peut m'aider car je désepère un peu j'avoue.

    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
    package InterfaceDessin;
    
    import java.awt.Color;
    import java.awt.Graphics;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    class PanneauDessin extends JPanel {
       Graphics graf ;
       public void paintComponent(Graphics g) {
    	  
    	    this.graf = g ;
    	  
    	  }
       public PanneauDessin() {
    	   
    	  
    		graf.setColor(Color.red);  // ERREUR NullPointException
    		graf.fillOval(0,0,40,40);
    	   graf.dispose();
    		
    	}
    }
    public class TestPanneau {
    	
    	public static void main(String[] args) {
    		
    		JFrame mafenetre = new JFrame() ;
    		mafenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		mafenetre.setContentPane(new PanneauDessin()) ;
    		mafenetre.setTitle("Interface Dessin");
    		mafenetre.setLocation(200, 200);
    		mafenetre.setSize(400,400);
    		
    		mafenetre.setVisible(true);
    		
    	}
    }
    Merci d'avance ...

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    Premièrement, tu as une NullPointerException parce que graf vaut null. Il vaut null parce qu'on ne lui a affecté aucune valeur lors de l'invocation de graf.setColor(Color.red) : forcément, c'est la première instruction du constructeur, rien ne s'est exécuté vant, sauf les initialisations statiques et les initialisations dans les déclarations des attributs.

    Ensuite, il ne faut jamains chercher à intercepter l'instance de contexte graphique, pour l'utiliser en dehors de la méthode qui est invoquée par Swing (méthode paint, paintComponent, et consorts). Et il ne faut surtout pas en disposer !!! Cette instance est gérée par Swing et ce n'est pas à toi de t'en occuper. Tu dois juste t'en servir pour dire ce que tu veux afficher dans le composant.

    Pourquoi cherches-tu à faire l'affichage dans le constructeur (avec une bidouille en plus), alors la méthode paint est fait pour faire l'affichage ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class PanneauDessin extends JPanel {
       protected void paintComponent(Graphics g) {
     
    	 super.paintComponent(g); // n'enlève pas la gestion standard du dessin du composant
     
    	 g.setColor(Color.RED);  
    	 g.fillOval(0,0,40,40);
     
       }
    }
    Tout simplement.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Par défaut
    OK, en effet c'est simple et ça marche. Merci beaucoup....

  4. #4
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Par défaut
    Maintenant j'ai ajouté un bouton et j'aimerais que d'appuyer dessus redessine le disque en une autre couleur.
    Donc j'ai implémenté actionlistener et sa méthode actionperformed ou je change une variable globale couleur.
    Mais est ce qu'il faut que je le redessine ou est ce que c'est redessiné auto ?

    Je suis perdu !!!

    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
    package InterfaceDessin;
     
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
     
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
    class PanneauDessin extends JPanel {
       Color Couleur ;
       PanneauDessin(Color couleur) {
          this.Couleur = couleur ;
       }
       protected void paintComponent(Graphics g) {
    	   super.paintComponent(g); // n'enlève pas la gestion standard du dessin du composant
     
    		 g.setColor(Couleur);  
    		 g.fillOval(0,0,40,40);
    		 //g.dispose();
    		 //repaint() ;
    	  }
     
    }
    public class TestPanneau implements ActionListener {
    	private static Color macouleur = Color.blue ;
    	public static void main(String[] args) {
     
    		JFrame mafenetre = new JFrame() ;
    		JButton changercouleur = new JButton("Changer Couleur") ;
    		mafenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		mafenetre.setContentPane(new PanneauDessin(macouleur)) ;
    		mafenetre.setTitle("Interface Dessin");
    		// mafenetre.setBackgroudColor(Color.white) ;
    		mafenetre.setLocation(200, 200);
    		mafenetre.setSize(400,400);
    		mafenetre.add(changercouleur) ;
    		//mafenetre.pack();
    		mafenetre.setVisible(true);
     
    	}
     
    	@Override
    	public void actionPerformed(ActionEvent e) {
    		// TODO Auto-generated method stub
    		if (macouleur.equals(Color.red)) macouleur = Color.blue ;
    		else macouleur = Color.red ;
     
    		//PanneauDessin(macouleur);
     
    	}
    }

  5. #5
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Oui, il faut demander de redessiner (appeler repaint() de l'instance de PanneauDessin), parce que Swing ne peut pas savoir que tu utilises une variable couleur et que tu veux que lorsque tu changes sa valeur, ceci doit être répercuté immédiatement à l'affichage.

    En revanche :

    • ta variable macouleur n'a aucune influence sur le dessin dans PanneauDessin, c'est l'attribut Couleur qui est utilisé. Elle n'est par ailleurs pas utile, puisque la la variable Couleur de la classe PanneauDessin suffit. Il sufffit simplement de faire un accesseur et un mutateur :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      public void setCouleur(Color couleur) {
      	   this.Couleur=couleur; // on change la couleur
      	   repaint(); // on redessin
         }
       
         public Color getCouleur() {
      	   return Couleur;
         }
    • Pour que l'action listener (l'instance de classe TestPanneau) puisse manipuler la couleur de dessin, il lui est nécessaire d'avoir la référence de cette classe, afin de pouvoir appeler les méthode getCouleur et setCouleur. Tu peux la passer par exemple au constructeur :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      public class TestPanneau implements ActionListener {
      	private PanneauDessin panneau;
      	public TestPanneau(PanneauDessin panneau) {
      		this.panneau=panneau;
      	}
    • Attention : tu changes le contentPane (tu le remplaces par l'instance de PanneauDessin) et ensuite tu ajoutes un bouton. Les deux vont se superposer. Il vaut mieux que tu ajoutes le PanneauDessin au centre du contentPane existant et le bouton au sud, comme ça ils ne superposeront pas. Mais le bouton va s'étendre sur toute la largeur de la fenêtre : il suffit que tu le mettes dans un JPanel intermédiaire et que tu mettes ce JPanel au sud du content pane. En plus ça te permettra d'ajouter d'autres boutons...
    • Fais une classe par fichier. N'utilise pas cette possibilité de Java de mettre des classes dans le même fichier qu'une classe public, ça n'apporte que de la confusion. Eventuellement, dans certains cas, tu peux faire des classes internes (elles sont à l'intérieur d'une autre classe), des classes anonymes locales (dans une méthode), ou éventuellement, très rarement des classes locales non anonymes.
    • il y a des conventions d'écriture en Java (elles servent à tout le monde de s'y retrouver plus rapidement en lisant le code, surtout celui d'un autre) : les noms de variables et de méthode doivent commencer par une minuscules. Les noms de package eux sont en minuscules. Les noms de classes commencent toujours par une majuscules. Et les constantes de type static final en majuscules (il y a eu une erreur à l'origine pour les constantes de la classe Color qui a été corrigée : préférer donc les constantes en majuscules (RED plutôt que red).


    Voici au final ce que ça donne :
    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
    package interfacedessin;
     
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Graphics;
     
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
     
    public class PanneauDessin extends JPanel {
       private Color couleur ;
       PanneauDessin(Color couleur) {
          this.couleur = couleur ;
       }
     
       public void setCouleur(Color couleur) {
    	   this.couleur=couleur;
    	   repaint();
       }
     
       public Color getCouleur() {
    	   return couleur;
       }
     
       protected void paintComponent(Graphics g) {
    	   super.paintComponent(g); // n'enlève pas la gestion standard du dessin du composant
     
    		 g.setColor(couleur);  
    		 g.fillOval(0,0,40,40);
     
    	  }
     
    	public static void main(String[] args) {
     
    		PanneauDessin panneauDessin = new PanneauDessin(Color.BLUE); // on créé l'instance de PanneauDessin avec la couleur bleue 
     
    		JFrame mafenetre = new JFrame() ;
     
    		JPanel panelBoutons = new JPanel(); // on créé un JPanel pour les boutons (layout par défaut : FlowLayout)
    		JButton changercouleur = new JButton("Changer Couleur") ;
    		changercouleur.addActionListener(new TestPanneau(panneauDessin)); // on ajoute l'action listener en lui passant la référence de l'instance de PanneauDessin
    		panelBoutons.add(changercouleur);
     
    		mafenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		mafenetre.getContentPane().add(panneauDessin) ; // on ajout le PanneauDessin au centre (par défaut le content pane a un BorderLayout, et pas de contrainte = BorderLayout.CENTER)
    		mafenetre.setTitle("Interface Dessin");
    		// mafenetre.setBackgroudColor(Color.white) ;
    		mafenetre.setLocation(200, 200);
    		mafenetre.setSize(400,400);
     
    		mafenetre.add(panelBoutons,BorderLayout.SOUTH) ; // on ajoute le panel des boutons au sud du content pane.
    		//mafenetre.pack();
    		mafenetre.setVisible(true);
     
    	}
     
    }
    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
    package interfacedessin;
     
    import java.awt.Color;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
     
    public class TestPanneau implements ActionListener {
    	private final PanneauDessin panneau;
    	public TestPanneau(PanneauDessin panneau) {
    		this.panneau=panneau;
    	}
     
    	@Override
    	public void actionPerformed(ActionEvent e) {
    		Color macouleur=panneau.getCouleur(); // on récupère la couleur du panneau avec l'accesseur
    		if (macouleur.equals(Color.RED)) macouleur = Color.BLUE; 
    		else macouleur = Color.RED;
    		panneau.setCouleur(macouleur); // on modifie la couleur avec le mutateur
    	}
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  6. #6
    Membre confirmé
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2016
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 85
    Par défaut
    Merci, quand je lis je comprends mais tout seul ...galère
    Mais ça marche... Bon, j'ai vraiment du mal. Parce que repaint, j'y avais pensé mais le compilateur n'était pas content de là ou je le mettais.

    Sinon j'ai lu des FAQ et on y dit qu'il ne faut pas mélanger swing et awt, mais on y est un peu obligés non ?

  7. #7
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par SeniorEric Voir le message
    Sinon j'ai lu des FAQ et on y dit qu'il ne faut pas mélanger swing et awt, mais on y est un peu obligés non ?
    SWING se base sur AWT, donc on utilise forcément des éléments de AWT quand on fait du SWING, comme la classe Color (ou Paint), les gestionnaires d'agencement (Layout Managers), etc, même Graphics/Graphics2D fait partie du package AWT. Quand on parle de ne pas mélanger SWING et AWT, on parle de ne pas mélanger les composants AWT et SWING. Donc ne pas utiliser de java.awt.Panel, mais un javax.swing.JPanel, par exemple.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

Discussions similaires

  1. Méthode générique qui renvoie une Map
    Par stof dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 01/03/2010, 14h37
  2. COUNT qui renvoie null au lieu de 0
    Par gomodo dans le forum Requêtes
    Réponses: 4
    Dernier message: 10/02/2008, 14h50
  3. Requête qui renvoie 'Null'
    Par Invit-é dans le forum VB 6 et antérieur
    Réponses: 14
    Dernier message: 11/06/2007, 17h32
  4. [SPL] Rewind() qui renvoie NULL
    Par fadeninev dans le forum Bibliothèques et frameworks
    Réponses: 6
    Dernier message: 06/06/2006, 15h44
  5. [JDBC]Un new qui renvoie null...
    Par Ditch dans le forum JDBC
    Réponses: 4
    Dernier message: 03/01/2005, 13h14

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