Problème avec java.awt.Graphics

Fermé
raphaelmoncaut Messages postés 21 Date d'inscription dimanche 5 avril 2015 Statut Membre Dernière intervention 19 avril 2018 - 8 août 2016 à 14:14
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 - 12 août 2016 à 21:01
Bonjour, je suis un bricoleur en java je veut dire par là que je fais avec ce que je connais et je ne connais pas grand chose, en ce moment je suis en train de faire un petit programme qui sert a afficher des stats sous forme de camembert et j'ai voulu créer une méthode qui faisais le travail à ma place.
Panel.java

package pack1;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;

public class Panel extends JPanel {
	
		public void paint(Graphics g) {
			super.paint(g);
			camembert(0, 0, 300, 90, 69, 40, false, g);
			camembert(500, 500, 300, 90, 56, 26, false, g);
		}
	    public void camembert(int positionx, int positiony, int taille, int depart, int pourcentage, int epaisseur, boolean sens_aiguilles_montre, java.awt.Graphics g) {
	    	super.paint(g);
	    	
	    	double angle = pourcentage * 3.6;
	    	if(sens_aiguilles_montre == true) depart = depart - (int) angle;
	    	for(int i = 0; i == 100; i++){System.out.println("jeuj");}
		    g.setColor(Color.RED);
		    g.fillArc(positionx, positiony, taille, taille, depart, (int) angle);
		    g.setColor(this.getBackground());
		    g.fillOval(epaisseur / 2 + positionx, epaisseur / 2 + positiony, taille - epaisseur, taille - epaisseur);
	    }
	    
}

la méthode en question s'appelle camembert
voici les classes Main et Fenetre si ça peut aider
Fenetre.java

package pack1;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Fenetre extends JFrame {
	
	Panel panel = new Panel();
	
	public Fenetre() {
		
		this.setTitle("A");
		//this.setLocation(0, 40);
		this.setSize(300, 300);
		this.setExtendedState(this.getExtendedState()|JFrame.MAXIMIZED_BOTH );
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setContentPane(panel);
		
		
		this.setResizable(true);
		this.setVisible(true);
		
	}
}


Main.java


package pack1;

/*
@author raphael
 */
public class Main {

	public static void main(String[] args) {
		Fenetre fen = new Fenetre();
	}
}


Voila pour le code, maintenant mon problème est :

- que je ne peut appeler la méthode camembert que depuis la méthode paint ou une méthode qui a comme paramètre entre autre "java.awt.Graphics" et que je suis obligé de rajouter "g" comme paramètre quand j'appelle la méthode .

- que je ne sait pas comment ajouter la couleur du camembert comme paramètre lorsque j'appelle la méthode (à part en envoyant le code RVB de la couleur, ce que j'aimerai éviter si c'est possible).

- que quand j'appelle la méthode deux fois seul le deuxième camembert est affiché.

on peut voir qu'ici la méthode est justement appelée deux fois et voici le résultat du launch :


on voit bien que seul le deuxième est visible.
j'espère que vous pourez m'aider, Merci d'avance.
cordialement.

2 réponses

KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
8 août 2016 à 19:07
Bonjour,

En partant de ton code de départ voici ce que l'on peut faire, je ne sais pas si ça réponds à toute tes questions mais ça t'avancera un peu.

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.GridLayout;

import javax.swing.JFrame;

public class Camembert extends Component {

    private static final long serialVersionUID = 1;

    private double pourcentage;
    private boolean sensAiguilleMontre;
    private double depart;
    private Color couleur;
    private double epaisseur;

    public Camembert(double pourcentage, boolean sensAiguilleMontre, double depart, Color couleur, double epaisseur) {
        this.pourcentage = pourcentage;
        this.sensAiguilleMontre = sensAiguilleMontre;
        this.depart = depart;
        this.couleur = couleur;
        this.epaisseur = epaisseur;
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        int angle = (int) (pourcentage * 3.6);
        int angleDepart = (int) (depart * 3.6);
        int taille = Math.min(getWidth(), getHeight());
        int positionX = (getWidth() - taille) / 2;
        int positionY = (getHeight() - taille) / 2;
        int tailleEpaisseur = (int) (taille * (100 - epaisseur) / 100);
        g.setColor(couleur);
        if (sensAiguilleMontre) {
            g.fillArc(positionX, positionY, taille, taille, angleDepart, (int) angle);
        } else {
            g.fillArc(positionX, positionY, taille, taille, -angleDepart, (int) -angle);
        }
        g.setColor(getBackground());
        g.fillOval((getWidth() - tailleEpaisseur) / 2, (getHeight() - tailleEpaisseur) / 2, tailleEpaisseur, tailleEpaisseur);
        g.setColor(couleur);
        g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("A");
        frame.setLayout(new GridLayout(2, 3));

        frame.add(new Camembert(25, true,  0, Color.RED,    50)); // cas de base
        frame.add(new Camembert(25, false, 0, Color.RED,    50)); // on change le sens
        frame.add(new Camembert(25, true,  5, Color.GREEN,  50)); // on décale le départ
        frame.add(new Camembert(75, true,  0, Color.BLUE,   50)); // on change le pourcentage
        frame.add(new Camembert(25, true,  0, Color.ORANGE, 25)); // on diminue l'épaisseur

        frame.setSize(300, 300);
        frame.setLocationRelativeTo(null);
        // frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}
0
raphaelmoncaut Messages postés 21 Date d'inscription dimanche 5 avril 2015 Statut Membre Dernière intervention 19 avril 2018 11
Modifié par raphaelmoncaut le 8/08/2016 à 23:07
re, je te remercie beaucoups même si je n'ai pas compris grand chose mais si j'ai bien compris (paradoxe :) ) c'est la JFrame dispatche les différents éléments toute seule et je dois avouer que ce n'est pas bête mais pas vraiment ce que je voulais. je préférerai les dispatcher comme bon me semble et leur donner la taille que je veut, de plus j'aimerai que les "camemberts" puissent en quelque sorte se chevaucher (j'ai fait un montage photo pourri pour expliquer de quoi je parle (en bas a gauche)).



en attente de ta réponse.
cordialement.
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
8 août 2016 à 23:34
"je n'ai pas compris grand chose"
Si tu as des questions je peux y répondre.

"je préférerai les dispatcher comme bon me semble et leur donner la taille que je veut"
C'est possible, j'ai fait un
frame.setLayout(new GridLayout(2, 3));
pour avoir une grille de 6 cases mais on peut mettre le layout à null en mode free-style.

"j'aimerai que les "camemberts" puissent en quelque sorte se chevaucher"
Il va falloir aller un peu plus loin dans le code alors, car il faut représenter les différentes portions du camemberts et distinguer les paramètres de chaque portion (couleur, pourcentage) avec les paramètres du camembert lui même (sens, départ, épaisseur).

Je n'ai pas vérifié complètement :

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;

import javax.swing.JFrame;

class Portion {
    private double pourcentage;
    private Color couleur;

    public Portion(double pourcentage, Color couleur) {
        this.pourcentage = pourcentage;
        this.couleur = couleur;
    }

    public double getPourcentage() {
        return pourcentage;
    }

    public Color getCouleur() {
        return couleur;
    }
}

class Camembert extends Component {

    private static final long serialVersionUID = 1;

    private boolean sensAiguilleMontre;
    private double depart;
    private double epaisseur;
    private Portion[] portions;

    public Camembert(boolean sensAiguilleMontre, double depart, double epaisseur, Portion... portions) {
        this.sensAiguilleMontre = sensAiguilleMontre;
        this.depart = depart;
        this.epaisseur = epaisseur;
        this.portions = portions;
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        int angleDepart = (int) ((sensAiguilleMontre ? depart : -depart) * 3.6);
        int taille = Math.min(getWidth(), getHeight());
        int positionX = (getWidth() - taille) / 2;
        int positionY = (getHeight() - taille) / 2;
        int tailleEpaisseur = (int) (taille * (100 - epaisseur) / 100);
        for (Portion portion : portions) {
            g.setColor(portion.getCouleur());
            int anglePortion = (int) (portion.getPourcentage() * 3.6);
            if (sensAiguilleMontre) {
                g.fillArc(positionX, positionY, taille, taille, angleDepart, (int) anglePortion);
                angleDepart += anglePortion;
            } else {
                g.fillArc(positionX, positionY, taille, taille, angleDepart, (int) -anglePortion);
                angleDepart -= anglePortion;
            }
        }
        g.setColor(getBackground());
        g.fillOval((getWidth() - tailleEpaisseur) / 2, (getHeight() - tailleEpaisseur) / 2, tailleEpaisseur, tailleEpaisseur);
        g.setColor(Color.BLACK);
        g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
    }
}

public class Test {
    public static void main(String[] args) {
        JFrame frame = new JFrame("A");
        frame.setLayout(null);

        Camembert cam = new Camembert(true, 0, 50, new Portion(75, Color.BLUE), new Portion(25, Color.RED));
        cam.setBounds(50, 50, 200, 200);
        frame.add(cam);

        frame.setSize(300, 300);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015 > KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024
8 août 2016 à 23:39
Remarque : je pense que le paramètre sensAiguilleMontre est superflu. D'une part il alourdi le code pour pas grand chose, de plus si on veut inverser le sens il suffit de jouer sur l'ordre des portions dans le tableau.
0
raphaelmoncaut Messages postés 21 Date d'inscription dimanche 5 avril 2015 Statut Membre Dernière intervention 19 avril 2018 11 > KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024
9 août 2016 à 20:31
oui je suis assez d'accord pour le sens et pour le reste il faudra que je me penche vraiment sur le code à tête reposée, demain je pense.
0
raphaelmoncaut Messages postés 21 Date d'inscription dimanche 5 avril 2015 Statut Membre Dernière intervention 19 avril 2018 11 > KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024
12 août 2016 à 16:26
j'ai analysé le code et j'ai quelques questions à te poser :
-que signifie final? parce que des fois eclipse me demande de mettre des variables en final et j'ai vu que tu l'as utilisé.
-à quoi sert serialVersionUID?
et je n'ai pas compris les lignes 32 et 45.

ça n'est pas préssé.
Cordiamement.
raphaelmoncaut
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
12 août 2016 à 21:01
"que signifie final?"
Le mot clé
final
a toujours le sens de "ne peut pas être modifié" même si ses propriétés exactes dépendent de s'il s'applique à une variable, une méthode, ou une classe...

Lorsque le mot clé
final
s'applique à une variable primitive (
int
,
double
...) ou un objet immuable (
String
par exemple) la valeur est assimilée à une constante.

Exemple :

final double PI = 3.14159265359;
double x = 2 * PI; // ok, on peut utiliser un final en lecture
PI = 19; // erreur : on ne peut pas utiliser un final en écriture

Les détails exhaustifs sont dans la spécification de Java : https://docs.oracle.com/javase/specs/jls/se8/html/index.html

"à quoi sert serialVersionUID?"
Dans notre cas, à rien.
Mais on fait un
extends Component
, sachant que
Component implements Serializable
or toutes les classes qui sont sérialisables devraient avoir un
serialVersialUID
, si tu l'enlèves tu auras un warning, j'ai mis 1 par défaut, ça n'a aucune importance.

"je n'ai pas compris les lignes 32 et 45"

Ligne 32 :
private Portion[] portions;

Pour construire un camembert on a plusieurs portions comme dans mon main :

new Camembert(true, 0, 50,
    new Portion(75, Color.BLUE),
    new Portion(25, Color.RED))

Pour stocker ces différentes portions il faut les stocker dans un tableau de portions, la ligne 32 déclare juste ce tableau. Puis dans le constructeur on a
this.portions = portions;
pour l'initialiser et enfin on l'utilise au moment du paint avec
for (Portion portion : portions) {
ce qui permet de dessiner chaque portion les unes à la suite des autres (ce qui est le but du camembert).

Ligne 45 :
int taille = Math.min(getWidth(), getHeight());


Cela se voyait bien sur mon premier exemple, quand j'avais un Layout dynamique, si tu redimensionnait la fenêtre le camembert changeait de taille.
getWidth()
et
getHeight()
nous indique la largeur et la hauteur du composant (que j'ai matérialisé par un rectangle), ici je calcule la taille du camembert (qui est rond) à partir de la plus petite de ces deux dimensions afin qu'il prenne toute la place sur une des deux dimensions mais sans déborder.


Camembert cam = new Camembert(true, 0, 50,
    new Portion(75, Color.RED),
    new Portion(25, Color.GREEN));
cam.setBounds(50, 50, 200, 150); // 200 de largeur, 150 de hauteur
0