Besoin d'aide avec un programme Java graphique

Fermé
SnPsn - Modifié le 2 oct. 2022 à 14:37
 SnPsn - 3 oct. 2022 à 18:43

Bonjour,

Je suis ici pour demander de l'aide, parce que je n'arrive pas a coder mon programme. J'ai crée un composant de dessin CercleCool.java(classe qui dérive de JPanel) qui dessinera deux cercles superposés. 

Le grand cercle est bleu et plein, et possède un diamètre de 80 pixels

Le petit cercle est tracé à l’aide d’un contour de couleur jaune, et son diamètre sera toujours égal à 75% de celui du grand cercle (du coup moi, j'ai fait (80*75)/100, parce que ca m'a semblé logique... Si c'est une erreur, que quelqu'un me fasse signe s'il vous plait!) 

Une ligne horizontale rouge le sépare en deux: (j'utilise un objet Line2D.Doubl) et les traits ont une largeur de 5 pixels et l'anticrénelage est activé.

Aussi les cercles devront être toujours exactement centrés dans le composant de dessin, peu importe la taille des cercles et la taille du composant

En voici une image :

Seulement, je n'arrive pas a mettre la ligne horizontale rouge qui sépare les cercles. Je n'arrive pas non plus a mettre de l'épaissir (mon 5 pixels) sur mon cercle jaune SANS le fill 

C'est ce que je veux avoir :

Voici le code de ma classe CercleCool.java

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;

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


public class CercleCool extends JPanel {
    private static final long serialVersionUID = 1L;

    private Ellipse2D.Double cercleCentreB, cercleCentreJ, cercleContour;
    private double coinX1 = 30, coinY1=50;
    private double diametreCercleB = 80;
    private double diametreCercleJ = ((80*75)/100);
    double contour = 5;

    public CercleCool() {

        setBackground(Color.BLACK); //arriere-plan
        setPreferredSize(new Dimension(400,150));     //initial mais redimensionnable
    }

    public void paintComponent(Graphics g) {    
        super.paintComponent(g); 
        Graphics2D  g2d = (Graphics2D) g;

        cercleCentreB = new Ellipse2D.Double(getWidth()/2.0-diametreCercleB/2.0, 
                getHeight()/2.0-diametreCercleB/2.0,
                diametreCercleB, diametreCercleB);

        g2d.setStroke( new BasicStroke(1) );
        g2d.setColor( Color.BLUE );    
        g2d.draw(cercleCentreB); 
        g2d.fill(cercleCentreB);

        cercleCentreJ = new Ellipse2D.Double(getWidth()/2.0-diametreCercleJ/2.0, 
                getHeight()/2.0-diametreCercleJ/2.0,
                diametreCercleJ, diametreCercleJ);
        g2d.setStroke(new BasicStroke(1));
        g2d.setColor( Color.YELLOW);    
        g2d.draw(cercleCentreJ); 
        
        g2d.setColor(Color.RED);
        g2d.draw(new Line2D.Double());

    }
}

Merci a la personne qui pourra m'aider :(

A voir également:

1 réponse

KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
2 oct. 2022 à 14:37

Bonjour,

Concernant ta ligne rouge, tu as fait g2d.draw(new Line2D.Double()); mais c'est insuffisant car tu ne précises pas ses coordonnées ! Par défaut ça trace une ligne du point (0,0) vers le point (0,0), c'est à dire un unique point rouge tout en haut à gauche (il faut avoir de bon yeux, mais on le devine sur ton image)
Tu devrais plutôt utiliser le constructeur Line2D.Double(x1, y1, x2, y2) 

Quant à l'épaisseur de ton cercle jaune, tu as fait g2d.setStroke(new BasicStroke(1));
Erreur d'étourderie : tu devrais mettre 5 à la place du 1...

Enfin, pour le crénelage tu peux faire :

g2d.setRenderingHints(
    new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
);

Remarque : il n'est pas nécessaire de faire ton dessin dans un JPanel (un containeur d'autres objets), tu pourrais considérer d'étendre un java.awt.Component (l'objet le plus simple - donc le plus performant), il n'y aurait qu'à changer la méthode paintComponent en paint et garder tout le reste de ton code à l'identique.


0

Merci beaucoup pour votre réponse!  

Pour la ligne rouge, je sais bien que je dois mettre les coordonnées des x et des y, seulement, je n'arrive pas a les situer. J'en suis rendue pour mettre  Line2D.Double(0, 0, 180, 120) 

Je sais que ce n'est pas bon, vu que j'ai une ligne inclinée et qui passe par tous les points du panel et non pas des deux extrémités de mon cercle jaune. Seulement, comme je l'ai dit, je n'arrive pas a percevoir les dimensions en java, d'où ca commence, d'où ca se termine, comment ca se positionne, etc... (on peut dire que je tape a l'aveugle des chiffres en espérant tomber sur les bonnes coordonnées...)  

Finalement, comme dernier soucis, j'ai ajouté un JSpinner représentant le diamètre du grand cercle (initialisé à 80). Dès que l’utilisateur change la valeur (entière) du JSpinner, le tout s’ajuste en restant proportionnel et centré (donc le cercle jaune ainsi que la ligne médiane). J'ai pensé a rajouter une méthode setAgrandir() (dans ma classe principale d'exécution), qui appelle un getDiamètre puis qui prend le 80 et le modifie (mais c'est plus complexe que ce que j'avais imaginé...) Puis peut-être que ce n'est pas la meilleure façon de faire.

PS : le seul panel affecté par le code est celui de gauche. Modifier le 2e a droite n'est pas voulu (on peut l'ignorer)  

Voici le code de ma classe graphique :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;

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


public class CercleCool extends JPanel {
    private static final long serialVersionUID = 1L;

    private Ellipse2D.Double cercleCentreB, cercleCentreJ, cercleContour;
    private double coinX1 = 30, coinY1=50;
    private double diametreCercleB = 80;
    private double diametreCercleJ = ((80*75)/100);
    private double contour = 5;
    private double LineGrosseur = 5;
    private int texteX=10;
    private boolean medianeEnlever = true;
    private Color couleurVoulu = Color.BLUE;
    private Color couleurInitial = Color.BLUE;

    public CercleCool() {

        setBackground(Color.BLACK); //arriere-plan
        setBounds(30,50 ,180, 120);
        setPreferredSize(new Dimension(180, 120));
        setLayout(null);

    }

    public void paintComponent(Graphics g) {    
        super.paintComponent(g); 
        Graphics2D  g2d = (Graphics2D) g;

        cercleCentreB = new Ellipse2D.Double(getWidth()/2.0-diametreCercleB/2.0, 
                getHeight()/2.0-diametreCercleB/2.0,
                diametreCercleB, diametreCercleB);

        g2d.setStroke(new BasicStroke(1));
        g2d.setColor(couleurVoulu);    
        g2d.draw(cercleCentreB); 
        g2d.fill(cercleCentreB);

        cercleCentreJ = new Ellipse2D.Double(getWidth()/2.0-diametreCercleJ/2.0, 
                getHeight()/2.0-diametreCercleJ/2.0,
                diametreCercleJ, diametreCercleJ);
        g2d.setStroke(new BasicStroke(5));
        g2d.setColor(Color.YELLOW);    
        g2d.draw(cercleCentreJ); 
        g2d.setRenderingHint(      
                RenderingHints.KEY_ANTIALIASING, 
                RenderingHints.VALUE_ANTIALIAS_ON );
        g2d.draw(cercleCentreJ);
        g2d.setColor(Color.RED);
        if(medianeEnlever) {
            g2d.draw(new Line2D.Double(0, 0, 180, 120));
        }
        g2d.setColor(couleurVoulu.MAGENTA);
        g2d.draw(creerTriangleCentre());
        g2d.setRenderingHint(      
                RenderingHints.KEY_ANTIALIASING, 
                RenderingHints.VALUE_ANTIALIAS_ON );

        //ajout de texte graphique 
        g2d.setColor( Color.ORANGE);             
        g2d.drawString("Text", texteX, getHeight()- 25);

    }

    public void setMedianeEnlever(boolean enlever) {
        this.medianeEnlever = enlever;
        repaint();

    }
    private Path2D.Double creerTriangleCentre() {    

        Path2D.Double triangle = new Path2D.Double();
        double s1x = getWidth()/2.0;
        double s1y = getHeight()/2.0 - diametreCercleB/2.0;

        double s2x = getWidth()/2.0 - diametreCercleB/2.0;
        double s2y = getHeight()/2.0 + diametreCercleB/2.0;

        double s3x = getWidth()/2.0 + diametreCercleB/2.0;
        double s3y = getHeight()/2.0 + diametreCercleB/2.0;

        triangle.moveTo(s1x,  s1y);
        triangle.lineTo(s2x,  s2y);
        triangle.lineTo(s3x,  s3y);
        triangle.closePath();

        return(triangle);
    }

    public void setCouleurVoulu() {
        this.couleurVoulu = Color.GREEN;
        repaint();
    }

    public void setCouleurInitial() {
        this.couleurInitial = Color.BLUE;
        repaint();

    }
}

Code de ma classe main :

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.JCheckBox;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JRadioButton;
import javax.swing.ButtonGroup;

public class Application extends JFrame {

    private JPanel contentPane;
    private final ButtonGroup buttonGroup = new ButtonGroup();
    JRadioButton radVert = new JRadioButton("Vert");
    JRadioButton radBleu = new JRadioButton("Bleu");

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Application frame = new Application();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public Application() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 571, 355);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

        setContentPane(contentPane);
        contentPane.setLayout(null);

        CercleCool jpCercleCool = new CercleCool();        
        jpCercleCool.setBounds(10, 11, 180, 120);
        contentPane.add(jpCercleCool);
        jpCercleCool.setLayout(null);

        JLabel lblTailleDuGrandCercle = new JLabel("Taille du grand cercle en pixels : ");
        lblTailleDuGrandCercle.setBounds(10, 156, 190, 39);
        contentPane.add(lblTailleDuGrandCercle);

        JSpinner spnTailleGrandCercle = new JSpinner();
        spnTailleGrandCercle.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                //debut 


                //fin
            }
        });
        spnTailleGrandCercle.setBounds(200, 163, 44, 24);
        spnTailleGrandCercle.setValue(80);
        contentPane.add(spnTailleGrandCercle);

        JCheckBox chcLigneMediane = new JCheckBox("Ligne mediane");
        chcLigneMediane.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                // debut
                if(chcLigneMediane.isSelected())  {
                    jpCercleCool.setMedianeEnlever(false);
                } else {
                    jpCercleCool.setMedianeEnlever(true);
                }
                //fin 
            }
        });
        chcLigneMediane.setBounds(10, 286, 125, 23);
        contentPane.add(chcLigneMediane);

        JLabel lblChoixCouleur = new JLabel("Couleur du grand cercle :");
        lblChoixCouleur.setBounds(10, 194, 180, 14);
        contentPane.add(lblChoixCouleur);
        buttonGroup.add(radVert);
        radVert.setBounds(10, 243, 109, 23);
        contentPane.add(radVert);
        buttonGroup.add(radBleu);
        radBleu.setSelected(true);
        radBleu.setBounds(10, 215, 109, 23);
        contentPane.add(radBleu);                
        
        CercleCool jpCercleCool2 = new CercleCool();
        jpCercleCool2.setBounds(338, 11, 180, 120);
        contentPane.add(jpCercleCool2);
        jpCercleCool2.setLayout(null);
        radVert.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //debut
                if(radVert.isSelected()) {
                    jpCercleCool.setCouleurVoulu();    
                } else if (radBleu.isSelected()) {
                    jpCercleCool.setCouleurInitial();
                }                
                //fin 
                
            }
        });

    }
}

PS : mon bouton radio bleu ne fonctionne pas, mais je n'arrive pas a savoir pourquoi alors que j'y passe des heures dessus.

PS2 : juste prévenir que je suis encore un étudiant. Je fais mes débuts dans la programmation encore... Pour le moment donc je ne sais travailler qu'avec la méthode paintComponent

0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015 > SnPsn
3 oct. 2022 à 13:14

Bonjour,

 je n'arrive pas a percevoir les dimensions en java, d'où ca commence, d'où ca se termine, comment ca se positionne, etc... (on peut dire que je tape a l'aveugle des chiffres en espérant tomber sur les bonnes coordonnées...)  

Chaque méthode est différente et il faut regarder sa documentation pour savoir à quoi correspond chaque paramètre

Ensuite, il faut organiser ses idées et ne pas se laisser tenter par un copier-coller un peu trop facile. Si tu as besoin d'une valeur plusieurs fois, stockes là dans une variable dédiée, bien nommée, ça évite ensuite de se mélanger les pinceaux.

Par exemple tu ne devrais pas écrire :

cercleCentreB = new Ellipse2D.Double(getWidth()/2.0-diametreCercleB/2.0,
    getHeight()/2.0-diametreCercleB/2.0,
    diametreCercleB, diametreCercleB);

Mais tu devrais écrire :

double xCentre = getWidth() / 2;
double yCentre = getHeight() / 2;
double rayonCercleB = diametreCercleB / 2;

cercleCentreB = new Ellipse2D.Double(
    xCentre - rayonCercleB, // the X coordinate of the upper-left corner of the framing rectangle
    yCentre - rayonCercleB, // the Y coordinate of the upper-left corner of the framing rectangle
    diametreCercleB, // the width of the framing rectangle
    diametreCercleB  // the height of the framing rectangle
);

Ainsi ta ligne se trace comme ceci :

g2d.draw(new Line2D.Double(
    xCentre - rayonCercleJ, // the X coordinate of the start point
    yCentre,                // the Y coordinate of the start point
    xCentre + rayonCercleJ, // the X coordinate of the end point
    yCentre                 // the Y coordinate of the end point
));

Quant à ton JSpinner, ce n'est pas si compliqué que ça, tu as déjà mis le ChangeListener dans ton code, il n'y aurait donc que deux lignes à ajouter :

spnTailleGrandCercle.addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) {
        //debut 
        jpCercleCool.setDiametreCercleB((int) spnTailleGrandCercle.getValue());
        jpCercleCool.repaint();
        //fin
    }
});

Il faut bien sur créer cette méthode dans CercleCool :

public void setDiametreCercleB(double diametreCercleB) {
    this.diametreCercleB = diametreCercleB;
}

PS. Vu que le diametreCercleJ est calculé à partir du diametreCercleB, il faudrait plutôt mettre ce calcul dans la méthode paintComponent, sinon la valeur ne sera pas recalculée à chaque affichage et le cercle jaune ne sera pas redimensionné.

0
SnPsn > KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024
3 oct. 2022 à 17:31

Alors, merci beaucoup, tout fonctionne pour le calcul, etc.

Tout ce qui ne fonctionne pas, c'est la ligne rouge et les radios boutons (seulement le bouton bleu pour une raison qui m'échappe).

Pour la ligne rouge, j'ai exactement reproduit ce que vous m'aviez montré, en mettant bien cette fois-ci des noms de variables au lieu de chiffres. Ca ne fonctionne pas malgré tout... 

Pour le bouton bleu, aucune idée   

Code : 

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.JCheckBox;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JRadioButton;
import javax.swing.ButtonGroup;
import javax.swing.SpinnerNumberModel;

public class Application extends JFrame {

	private JPanel contentPane;
	private final ButtonGroup buttonGroup = new ButtonGroup();
	private int valeurSpin, valeurS;
	JRadioButton radVert = new JRadioButton("Vert");
	JRadioButton radBleu = new JRadioButton("Bleu");
	CercleCool jpCercleCool2 = new CercleCool();

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Application frame = new Application();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Application() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 571, 355);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

		setContentPane(contentPane);
		contentPane.setLayout(null);

		CercleCool jpCercleCool = new CercleCool();		
		jpCercleCool.setBounds(10, 11, 180, 120);
		contentPane.add(jpCercleCool);
		jpCercleCool.setLayout(null);

		JLabel lblTailleDuGrandCercle = new JLabel("Taille du grand cercle en pixels : ");
		lblTailleDuGrandCercle.setBounds(10, 156, 190, 39);
		contentPane.add(lblTailleDuGrandCercle);

		JSpinner spnTailleGrandCercle = new JSpinner();
		spnTailleGrandCercle.setModel(new SpinnerNumberModel(Integer.valueOf(80), Integer.valueOf(0), null, Integer.valueOf(1)));
		spnTailleGrandCercle.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				//debut 

				valeurSpin = (int) spnTailleGrandCercle.getValue();
				valeurS = (int) spnTailleGrandCercle.getValue();
				valeurS = ((valeurS*75)/100);
				jpCercleCool.setDiametre(valeurSpin);
				jpCercleCool.setDiametrePetit(valeurS);



				//fin
			}
		});
		spnTailleGrandCercle.setBounds(200, 163, 44, 24);
		spnTailleGrandCercle.setValue(80);
		contentPane.add(spnTailleGrandCercle);

		JCheckBox chcLigneMediane = new JCheckBox("Ligne médiane");
		chcLigneMediane.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				// debut
				if(chcLigneMediane.isSelected())  {
					jpCercleCool.setMedianeEnlever(false);
				} else {
					jpCercleCool.setMedianeEnlever(true);
				}
				//fin 
			}
		});
		chcLigneMediane.setBounds(10, 286, 125, 23);
		contentPane.add(chcLigneMediane);

		JLabel lblChoixCouleur = new JLabel("Couleur du grand cercle :");
		lblChoixCouleur.setBounds(10, 194, 180, 14);
		contentPane.add(lblChoixCouleur);
		buttonGroup.add(radVert);
		radVert.setBounds(10, 243, 109, 23);
		contentPane.add(radVert);
		buttonGroup.add(radBleu);
		radBleu.setSelected(true);
		radBleu.setBounds(10, 215, 109, 23);
		contentPane.add(radBleu);				

		jpCercleCool2.setBounds(378, 11, 100, 100);
		contentPane.add(jpCercleCool2);
		jpCercleCool2.setLayout(null);
		radVert.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				//debut
				if (radVert.isSelected()) {
					jpCercleCool.setCouleurVoulu();	
				} else if (radBleu.isSelected()) {
					jpCercleCool.setCouleurInitial();
				}				
				//fin 

			}

Code méthode dans la classe CercleCool :

private Color couleurVoulu = Color.BLUE;
private Color couleurInitial = Color.BLUE;



public void setCouleurVoulu() {
		this.couleurVoulu = Color.GREEN;
		repaint();
	}

	public void setCouleurInitial() {
		this.couleurInitial = Color.BLUE;
		repaint();

	}
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015 > SnPsn
3 oct. 2022 à 18:23

Il faudrait que tu remettes ton code complet pour déboguer la partie sur la ligne rouge, vu où elle est placée je dirais que tu utilises des valeurs qui valent 0 au lieu de correctement les calculer.

Pour le changement de couleur je ne comprends pas pourquoi tu as deux variables couleurVoulu et couleurInitial, une seule devrait suffire que tu pourrais renommer couleurGrandCercle.

0
SnPsn > KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024
3 oct. 2022 à 18:43

Au départ j'en avais qu'une seule, comme ca ne marchait pas j'en ai mis deux... 

0