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 :

Java2D et clipping


Sujet :

AWT/Swing Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    82
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Orne (Basse Normandie)

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

    Informations forums :
    Inscription : Avril 2013
    Messages : 82
    Par défaut Java2D et clipping
    Bonjour,

    j'essaie de faire un peu de java2d et j'ai un problème que je n'arrive pas à résoudre.

    J'ai un dessin dans lequel j'ai un octogone et je veux faire un trait à l'intérieur (ou plutôt un rectangle). Je voudrais que quelque soit la taille du trait, on n'affiche que la partie qui est à l'intérieur de l'octogone.

    j'ai regardé un peu sur le net et apparemment la méthode Clip() répond à ma question.
    Cependant, je n'est pas eu le résultat que je voulais.

    Voici mon 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    public class VuePiece extends JPanel {
     
    	// Déclarer 2 tableaux pour les coordonnées
    		int x[], y[];
    		public void init()
    		{
    			// Définir la couleur de fond
    			setBackground(Color.gray);
    			// Définir les coordonnées de chaque point du polygone
    			x = new int[8];
    			y = new int[8];
     
    			x[0] = 0;  y[0] = 40;
    			x[1] = 40;  y[1] = 0;
    			x[2] = 80; y[2] = 0;
    			x[3] = 120; y[3] = 40;
    			x[4] = 120; y[4] = 80;
    			x[5] = 80; y[5] = 120;
    			x[6] = 40;  y[6] = 120;
    			x[7] = 0;  y[7] = 80;
    		}
     
    		public void paint(Graphics g)
    		{
    			Graphics2D g2 = (Graphics2D) g; 
    			init();
    			Polygon polygone = new Polygon(x,y,x.length);
    			g.setColor(Color.black);
    			g.drawPolygon(polygone);
     
    			AffineTransform rotation = new AffineTransform();
    			rotation.concatenate(AffineTransform.getRotateInstance(3*(Math.PI)/4,60,60));
    			g2.transform(rotation);
    			g2.clip(polygone);
     
    			Rectangle rect= new Rectangle(55, -10, 10, 130); 
    			g2.fillRect(rect.x, rect.y, rect.width, rect.height);
    		}
    }
    et voici le résultat:
    Nom : Sans titre.png
Affichages : 189
Taille : 2,1 Ko

    Voici le résultat si je supprime la ligne g2.clip(polygone);
    Nom : Sans titre2.png
Affichages : 193
Taille : 2,1 Ko

    Comme vous le voyez, avec le clip() c'est un peu mieux mais sa dépasse quand même.
    Je voudrais que le trait ne dépasse pas du tout et je ne sais pas si je suis sur la bonne voie.

    Merci pour vos réponses.

  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,

    La transformée affine, tout comme le clipping, s'applique au contexte graphique pour l'ensemble des opérations faites après (des opérations influencées par la tranformée affiine).

    Donc le polygone de clip est affecté par la transformée affine : d'ailleurs si tu fais g.drawPolygon(polygone);, tu verras la zone de clipping que tu mets en place, et donc tu verras un petit décalage, parce que ton octogone n'est pas centré sur le centre de la rotation.

    Pour régler le problème, tu l'auras compris, fait le setClip() avant le transform().

    Par ailleurs, il est de bon ton de toujours restituer le contexte graphique comme on l'a trouvé, pour que d'éventuels dessins fait après l'appel de la méthode dans le méme dessin ne soient pas affectés par les éléments (tranformée, clipping renderinghints, couleurs, etc...) que tu as modifiés. Pour ce faire, la méthode la plus simple est de créer un nouveau contexte à partir du premier (autre solution, plus bourrine, sauvegarder et restituer après).

    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
    public void paint(Graphics g)
    		{
    			Graphics2D g2 = (Graphics2D) g.create(); 
     
    			init();
    			Polygon polygone = new Polygon(x,y,x.length);
    			g.setColor(Color.black);
    			g.drawPolygon(polygone);
     
    			g2.clip(polygone);
     
    			AffineTransform rotation = new AffineTransform();
    			rotation.concatenate(AffineTransform.getRotateInstance(3*(Math.PI)/4,60,60));
    			g2.transform(rotation);
     
    			Rectangle rect= new Rectangle(55, -10, 10, 130); 
    			g2.fillRect(rect.x, rect.y, rect.width, rect.height);
     
    			g2.dispose();
    		}]
    A noter que puisque le polygone, le rectangle et la transformée sont fixes, on peut les créer dans le constructeur du composant, ce qui évite dans créer un nouveau de chaque à chaque appel de paint().
    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
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    82
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Orne (Basse Normandie)

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

    Informations forums :
    Inscription : Avril 2013
    Messages : 82
    Par défaut
    Merci pour ta réponse, ça marche en mettant le clip() avant la transformation affine.

    J'ai une autre question. Il n'y a que le polygone qui est fixe, le rectangle et la rotation vont apparaître grâce à des boutons.

    J'ai essayé de faire un constructeur qui me créer le polygone mais sa me renvoi une erreur qui me dit que "g" est null.
    (Je pense que je fais des erreurs de débutant )

    voici le 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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    public class VuePiece extends JPanel {
     
    	// Déclarer 2 tableaux pour les coordonnées
    		int x[], y[];
    		public Polygon polygone;
     
    		public VuePiece()
    		{
    			Graphics g = getGraphics();
     
    			setBackground(Color.gray);
    			x = new int[8];
    			y = new int[8];
     
    			x[0] = 0;  y[0] = 40;
    			x[1] = 40;  y[1] = 0;
    			x[2] = 80; y[2] = 0;
    			x[3] = 120; y[3] = 40;
    			x[4] = 120; y[4] = 80;
    			x[5] = 80; y[5] = 120;
    			x[6] = 40;  y[6] = 120;
    			x[7] = 0;  y[7] = 80;
     
    			polygone = new Polygon(x,y,x.length);
    			g.setColor(Color.black);
    			g.drawPolygon(polygone);
    		}
     
    		public void paint(Graphics g)
    		{
    			Graphics2D g2 = (Graphics2D) g; 
    			g2.clip(this.polygone);
     
    			AffineTransform rotation = new AffineTransform();
    			rotation.concatenate(AffineTransform.getRotateInstance((Math.PI)/4,60,60));
    			g2.transform(rotation);
     
     
    			Rectangle rect= new Rectangle(55, -10, 10, 130); 
    			g2.fillRect(rect.x, rect.y, rect.width, rect.height);
    			g2.dispose();
    		}
    }
    En faite ce que je voudrais avoir au final, c'est un polygone qui s'affiche quand je créer une vuePiece.
    Quand je clique sur un bouton sa m'affiche un rectangle en plus du polygone.
    Quand je clique sur un autre bouton sa fait tourner le rectangle en affichant toujours mon polygone.

    Au niveau du code sa donnerai quelque chose comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public class VuePiece extends JPanel {
     
    	public VuePiece(){
    		//créer le polygone
    	}
     
    	public void rectangle(){
    		//créer le rectangle et l'affiche en plus du polygone
    	}
     
    	public void rotation(){
    		//rotation du rectangle et affichage en plus du polygone
    	}
    les methodes rectangle() et rotation() seront appeler quand on appuiera sur les boutons.

    Mais je ne vois pas comment faire?

  4. #4
    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
    Dans le constructeur, tu ne crées que l'instance de Polygone, son dessin, continuera de se faire dans paint().

    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
    public VuePiece() {
     
       int[] x = new int[8]; // pas besoin que les tableaux soient en variable de classe, puisque tu t'en sers que ici
       int[] y = new int[8];
     
       x[0] = 0;  y[0] = 40;
       x[1] = 40;  y[1] = 0;
       x[2] = 80; y[2] = 0;
       x[3] = 120; y[3] = 40;
       x[4] = 120; y[4] = 80;
       x[5] = 80; y[5] = 120;
       x[6] = 40;  y[6] = 120;
       x[7] = 0;  y[7] = 80;
     
       polygone = new Polygon(x,y,x.length); 
     
    }
    Si tu utilises des variables de classes pour la transformée (par exemple transform) et pour le rectangle (par exemple rectangle), les valeurs de ces 2 variables seront modifiés par tes boutons ( transform = AffineTransform... ).

    Après avoir modifié l'un ou l'autre, on appelle repaint() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // exemple pour transform :
    public void setTransform(AffineTransform transform) {
        this.transform = transform;
        repaint(); // redessiner
    }
    Dans la méthode paint() tu les utilises :

    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
    public void paint(Graphics g) {
     
       Graphics2D g2 = (Graphics2D) g.create(); 
     
       g.setColor(Color.BLACK);
       g.drawPolygon(polygone);
     
       if ( rectangle!=null ) { // s'il y a un rectangle, on le dessine
     
          g2.clip(polygone); 
     
          if ( transform!=null ) { // s'il y a une transformée, on l'applique
             g2.transform(transform);
          } 
     
          g2.fill(rectangle);
     
       }
     
       g2.dispose();
     
    }]
    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.

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    82
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Orne (Basse Normandie)

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

    Informations forums :
    Inscription : Avril 2013
    Messages : 82
    Par défaut
    Merci pour ta réponse

    j'ai modifié mon code comme tu m'a montré:
    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
     
    public class VuePiece extends JPanel {
     
    	// Déclarer 2 tableaux pour les coordonnées
    		int x[], y[];
    		public Polygon polygone;
    		public static Rectangle rectangle;
    		public static AffineTransform rotation;
    		public  VuePiece()
    		{
    			Graphics g = getGraphics();
    			// Définir la couleur de fond de l'applet
    			setBackground(Color.gray);
    			// Définir les coordonnées de chaque point du polygone
    			x = new int[8];
    			y = new int[8];
     
    			x[0] = 0;  y[0] = 40;
    			x[1] = 40;  y[1] = 0;
    			x[2] = 80; y[2] = 0;
    			x[3] = 120; y[3] = 40;
    			x[4] = 120; y[4] = 80;
    			x[5] = 80; y[5] = 120;
    			x[6] = 40;  y[6] = 120;
    			x[7] = 0;  y[7] = 80;
     
    			polygone = new Polygon(x,y,x.length);
     
    		}
     
    		public void paint(Graphics g)
    		{
     
    			Graphics2D g2 = (Graphics2D) g.create(); 
     
    			g.setColor(Color.black);
    			g.drawPolygon(polygone);
    			g2.clip(this.polygone);
     
    			if ( rectangle!=null ) { // s'il y a un rectangle, on le dessine
     
     
    			      if ( rotation!=null ) { // s'il y a une transformée, on l'applique
    			         g2.transform(rotation);
    			      } 
     
    			      g2.fill(rectangle);
     
    			   }
     
    			g2.dispose();
    		}
    		public void creerRectangleLarge() {
    			rectangle= new Rectangle(55, -10, 10, 130); 
    			repaint();
    		}
     
    		public void creerRotation45() {
    			rotation = new AffineTransform();
    			rotation.concatenate(AffineTransform.getRotateInstance((Math.PI)/4,60,60));	
    			repaint();
    		}
     
    }
    C'est exactement ce que je voulais et sa marche bien.

    J'ai juste un problème bizarre, quand je clique sur le bouton pour afficher le rectangle j'ai mon background qui se modifie comme ceci:
    Nom : Sans titre.png
Affichages : 171
Taille : 4,5 Ko
    L'image en background est une partie de ma fenêtre.

    Je ne vois d'où sa peut venir.

  6. #6
    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
    En fait, il faut savoir que SWING recycle le contexte graphique : le fond que tu vois, c'est justement parce que tu dessines dans un contexte qui a servi à dessiner autre chose.

    Bien sûr, d'habitude, SWING fait le nettoyage, mais en enlevant l'appel à super.paint(g) dans ta rédéfiniition de paint(Graphics g), tu as supprimé la ligne qui appellait le code qui fait le nettoyage. Soit tu fais ce nettoyage toi-même (avec clearRect, ou fillRect) , soit tu laisses SWING le faire, en laissant faire le super.paint(g) (tant qu'à faire, c'est probablement mieux).

    Plus de détails sur une discussion récente sur le même sujet.

    Par ailleurs, tu peux enlever la ligne Graphics g = getGraphics(); de ton constructeur, elle ne sert rien (tu n'utilises pas g, mais en plus, il faudrait pas le faire ici au cas où).


    [EDIT]Et je n'avais pas vu que tes variables rectangle et rotation étaient static et public: évite qu'elles soient public (ça évite qu'on puisse modifier ces variables (et du coup ne pas appeler le repaint() nécessaire). Évite au maximum static (je dirais même tant que tant que tu n'as pas parfaitement compris la portée de l'utiilisation d'un static, ne l'utilise jamais, même si ton IDE te propose de résoudre un cas d'erreur comme ça). En fait, dans ton cas, ça fait que tout les panels vont se partager le même Rectangle, et la même Rotation : dès que tu vas en utiliser plusieurs pour afficher des rectangles et des rotations différentes, ça va plus fonctionner correctement. Chaque instance de VuePiece doit avoir sa propre instance de l'un ou de l'autre.
    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. [FLASH MX] Scrollbar associée à un movie-clip
    Par dens63 dans le forum Flash
    Réponses: 19
    Dernier message: 05/06/2006, 11h41
  2. Pb d'action sur un clip
    Par bencasp dans le forum Flash
    Réponses: 4
    Dernier message: 22/10/2003, 17h11
  3. Clipping et projection orthogonale
    Par Luke-77 dans le forum DirectX
    Réponses: 4
    Dernier message: 01/10/2003, 20h02
  4. [appli][Java2D]Pb scintillement Animation
    Par ddams dans le forum 2D
    Réponses: 2
    Dernier message: 25/04/2003, 11h57
  5. Chemin d'accès au clip et scenario en flash
    Par Gential dans le forum Flash
    Réponses: 4
    Dernier message: 28/02/2003, 10h10

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