Réaliser des transformations en java (GUI)

Fermé
Caroline - Modifié le 5 oct. 2022 à 20:17
KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 - 8 oct. 2022 à 11:06

Bonjour!

Je suis une étudiante en JAVA, qui fais encore ses débuts!

Je tente de faire des dessins simples pour mieux comprendre les transformations et les pré-transformations en java (une tache que je ne trouve pas facile du tout haha) 

Ceci est ma classe main

package application;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import composants.CarreFlexible;
import composants.CarreSurOval;
import composants.CercleDePastilles;
import java.awt.Color;

/**
 * Cette application permet de tester diverses instructions de transformations
 *
 */

public class AppTransformations extends JFrame {
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;

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

	/**
	 * Creer l'interface de l'application
	 * en y placant des instances des differents composants
	 */
	public AppTransformations() {
		setTitle("Transformations");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 766, 287);
		contentPane = new JPanel();
		contentPane.setBackground(Color.LIGHT_GRAY);
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		CarreSurOval carreSurOval = new CarreSurOval();
		carreSurOval.setBounds(28, 11, 183, 205);
		contentPane.add(carreSurOval);
		carreSurOval.setLayout(null);

		CercleDePastilles cercleDePastilles = new CercleDePastilles();
		cercleDePastilles.setBounds(221, 11, 205, 206);
		contentPane.add(cercleDePastilles);
		cercleDePastilles.setLayout(null);

		CarreFlexible carreFlexible = new CarreFlexible();
		carreFlexible.setBounds(451, 11, 207, 205);
		contentPane.add(carreFlexible);
		carreFlexible.setLayout(null);

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

				// change la taille du caree a l'aide du tourniquet

				//	carreFlexible.setGrandeur();



				//fin
			}
		});
		spnDimCareeVert.setModel(new SpinnerNumberModel(1, 1, 3, 1));
		spnDimCareeVert.setBounds(689, 103, 40, 38);
		contentPane.add(spnDimCareeVert);


	}//fin constructeur
}//fin classe

Pour ma première classe, j'essaie d'apprendre les rotations. Je réalise cependant qu'en faisant une rotation de mon oval, mon carré ne reste plus au centre. Je me demandais comment je peux le centrer ? 

package composants;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;

/**
 * Ce composant dessine un carre sur un oval, en utilisant une rotation.
 */

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

	/** diametre horizontal de l'oval en pixels **/
	private final double DIAM_HORIZ= 80;
	/** diametre vertical  de l'oval en pixels **/
	private final double DIAM_VERT = 150;
	/** cote du carre en pixels **/
	private final double COTE_CARRE = 40; 
	/** angle de rotation pour l'oval en degres**/
	private final double ROTATION = 22;

	/**
	 *  Creation du composant
	 */
	public CarreSurOval() {
		setBackground(Color.white);
	}

	/**
	 * Dessiner le contenu du composant
	 * @param g Le contexte graphique du composant
	 */
	@Override
	public void paintComponent(Graphics g) {
		Ellipse2D.Double oval;
		Rectangle2D.Double carre;
		double posXOval = getWidth()/2.0-DIAM_HORIZ/2;
		double posYOval = getHeight()/2-DIAM_VERT/2;
		double posXCentreOval = DIAM_HORIZ/2;

		double posXCaree = getWidth()/2.0-COTE_CARRE/2;
		double posYCaree = getHeight()/2.0-COTE_CARRE/2;

		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;


		//cree une oval 
		g2d.setColor(Color.magenta);
		AffineTransform  mat  =  g2d.getTransform();
		g2d.rotate(Math.toRadians(ROTATION), posXOval, posYOval);
		oval = new Ellipse2D.Double (posXOval, posYOval, DIAM_HORIZ, DIAM_VERT );
		g2d.fill(oval); 



		// cree un caree
		g2d.setColor(Color.yellow);
		/* g2d.rotate(Math.toRadians(-ROTATION), posXCaree, posYCaree); */
		g2d.setTransform(mat);
		carre = new Rectangle2D.Double(posXCaree, posYCaree,  COTE_CARRE, COTE_CARRE);
		g2d.fill(carre);	
		g2d.setTransform(mat);


	}//fin paintComponent


}//fin classe

Pour ma seconde classe, j'essaie d'apprendre les notions de transparences. Je voulais créer un cercle de petites pastilles qui tournent le long de mon grand carré, en changeant leur couleur vec la transparence, mais finalement, c'est plus dur que ce que je pensais. Si je ne me trompe pas, ma loop fait une rotation de 255 radians pour chaque itération au lieu d'une rotation raisonnable de 2pi/n ? 

package composants;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JPanel;

/**
 * Ce composant dessine un carrre et des pastilles dessinees en cercle.
 */

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

	/** rayon des petites pastilles, en pixels **/
	private final double RAYON_PASTILLE = 9;  		
	/** rayon du grand cercle sur lequel sont disposees les pastilles **/
	private final double RAYON_GROS_CERCLE = 80;   	
	/** nombre de pastilles a dessiner **/
	private final int NB_PASTILLES = 20;   	
	/** la transparence ira de 0 à 255 **/
	private final int MAX_TRANSPARENCE = 255;
	private int depart;
	private int bulle;

	/**
	 *  Creation du composant
	 */
	public CercleDePastilles() {
		setBackground(Color.cyan);
	}

	/**
	 * Dessiner le contenu du composant
	 * @param g Le contexte graphique du composant
	 */
	@Override
	public void paintComponent(Graphics g) {
		Ellipse2D.Double pastille, pastilleDuCentre;
		double coinXPastille, coinYPastille;
		int transparence;

		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

		double centreComposantX = getWidth()/2.0;
		double centreComponsantY= getHeight()/2.0;

		//on dessine le point rouge bien au centre
		coinXPastille = centreComposantX - RAYON_PASTILLE;
		coinYPastille = centreComponsantY - RAYON_PASTILLE;
		pastilleDuCentre  = new Ellipse2D.Double( coinXPastille, coinYPastille , RAYON_PASTILLE*2, RAYON_PASTILLE*2);
		depart = 1;

		g2d.setColor(Color.black);
		g2d.fill(pastilleDuCentre);

		//on dessine un carre dont le cote egale deux fois le rayon du gros cercle
		Rectangle2D.Double carre = new Rectangle2D.Double(centreComposantX-RAYON_GROS_CERCLE, centreComponsantY-RAYON_GROS_CERCLE, RAYON_GROS_CERCLE*2, RAYON_GROS_CERCLE*2 );
		g2d.draw(carre);

		//coin de la petite pastille 
		coinXPastille = centreComposantX  + RAYON_GROS_CERCLE - RAYON_PASTILLE;
		pastille = new Ellipse2D.Double(coinXPastille, coinYPastille, RAYON_PASTILLE*2, RAYON_PASTILLE*2);

		transparence = MAX_TRANSPARENCE;

		g2d.setColor( new Color(255, 30, 255, transparence)); 	
		g2d.fill(pastille);

		// creer une boucle de dessin 
		for(depart = 1; bulle < NB_PASTILLES; bulle++) {
			g2d.setColor(Color.MAGENTA);
			pastille = new Ellipse2D.Double(coinXPastille, coinYPastille, RAYON_PASTILLE*2, RAYON_PASTILLE*2);
			g2d.rotate(MAX_TRANSPARENCE, centreComposantX, centreComponsantY);
			g2d.fill(pastille);

		}




	}//fin paintComponent


}//fin classe

Ce que j'ai est a gauche, ce que je veux est a droite (voir ci-haut)

Finalement, j'ai crée un carré dans un carré. J'aimerais changer la taille du carré vert a mesure que je change la valeur du JSpinner (la valeur va de 1 min et 3 max). A 1, il ne se passe rien du tout, a 2 il grand de la moitié du grand carré, a 3 il a la même dimension que mon grand carré       

package composants;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JPanel;

public class CarreFlexible extends JPanel {
	/** numero d'identification pour la serialisation **/
	private static final long serialVersionUID = 1L;
	private final double COTE_CARRE = 55;
	private Rectangle2D.Double carre;
	private int valMin, valMax;
	private int scale;

	public CarreFlexible() {
		setBackground(Color.blue);
		carre = new Rectangle2D.Double( 0,  0,  COTE_CARRE, COTE_CARRE);
	}

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

		g2d.setColor(Color.green);
		g2d.fill(carre);	

		g2d.scale(valMin, valMax);



	}//fin paintComponent

	public void setGrandeur(int spn) {

	}


}//fin classe

En soi, voici mon application actuelle :

Et voici ce que je souhaite :

J'aimerais apprendre les bases des transformations. J'espère pouvoir en apprendre davantage si on peut m'aider c: 

Merci a la personne qui lira ce message et prendra le temps de me répondre! 

A voir également:

1 réponse

KX Messages postés 16752 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 août 2024 3 019
8 oct. 2022 à 11:06

Bonjour,

Pour la première question, tu as fait ta rotation autour du point (posXOval, posYOval) qui n'est pas le centre de ton ovale, mais son coin supérieur gauche, il faudrait donc changer comme ça :

g2d.rotate(Math.toRadians(ROTATION), getWidth()/2.0, getHeight()/2);

Par contre il faut appliquer une rotation opposé après avoir dessiné l'ovale, sinon le carré sera également affecté par cette rotation.

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    double posXCentre = getWidth() / 2.0;
    double posYCentre = getHeight() / 2.0;

    //cree une oval
    double posXOval = posXCentre - DIAM_HORIZ / 2;
    double posYOval = posYCentre - DIAM_VERT / 2;
    g2d.rotate(Math.toRadians(ROTATION), posXCentre, posYCentre);
    g2d.setColor(Color.magenta);
    Ellipse2D.Double oval = new Ellipse2D.Double(posXOval, posYOval, DIAM_HORIZ, DIAM_VERT);
    g2d.fill(oval);
    g2d.rotate(Math.toRadians(-ROTATION), posXCentre, posYCentre);

    // cree un carre
    double posXCarre = posXCentre - COTE_CARRE / 2;
    double posYCarre = posYCentre - COTE_CARRE / 2;
    g2d.setColor(Color.yellow);
    Rectangle2D.Double carre = new Rectangle2D.Double(posXCarre, posYCarre, COTE_CARRE, COTE_CARRE);
    g2d.fill(carre);
}

Pour la deuxième question, tu t'es complètement mélangé les pinceaux, dans ta boucle tu fais toujours g2d.setColor(Color.MAGENTA) donc forcément la couleur ne change pas selon la transparence, de plus tu fais g2d.rotate(MAX_TRANSPARENCE) ce qui n'a pas de sens, c'est un angle qu'il te faut, pas une couleur, sans oublier comme pour ta première question qu'il faut faire une rotation opposée pour pas cumuler les rotations.

//coin de la petite pastille
coinXPastille = centreComposantX  + RAYON_GROS_CERCLE - RAYON_PASTILLE;

// creer une boucle de dessin 
for(bulle = 0; bulle < NB_PASTILLES; bulle++) {
    double ratio = ((double) bulle) / NB_PASTILLES;
    
    transparence = (int) (ratio * MAX_TRANSPARENCE);
    g2d.setColor( new Color(255, 30, 255, transparence));
    pastille = new Ellipse2D.Double(coinXPastille, coinYPastille, RAYON_PASTILLE*2, RAYON_PASTILLE*2);
    
    double theta = ratio * 2 * Math.PI;
    g2d.rotate(theta, centreComposantX, centreComponsantY);
    g2d.fill(pastille);
    g2d.rotate(-theta, centreComposantX, centreComponsantY);
}

Enfin, troisième question, tu n'as rien fait du tout pour que ça fonctionne... Dans le stateChanged, tu as commenté le code carreFlexible.setGrandeur(); c'est pourtant bien là qu'il faut intervenir, quant à ton dessin du carré, il doit prendre en compte le scale, sinon il dessinera toujours la même chose.

JSpinner spnDimCareeVert = new JSpinner();
spnDimCareeVert.addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) {
        // change la taille du caree a l'aide du tourniquet
        carreFlexible.setGrandeur((int) spnDimCareeVert.getValue());
        carreFlexible.repaint();
    }
});
public class CarreFlexible extends JPanel {
    @Serial
    private static final long serialVersionUID = 1L;
    private static final double COTE_CARRE = 55;
    private int scale = 1;

    public void setGrandeur(int spn) {
        scale = spn;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.green);
        Rectangle2D.Double carre = new Rectangle2D.Double(0, 0, scale * COTE_CARRE, scale * COTE_CARRE);
        g2d.fill(carre);
    }
}

0