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

2D Java Discussion :

Grille hexagonale n'affiche pas


Sujet :

2D Java

  1. #1
    Membre régulier
    Grille hexagonale n'affiche pas
    Bonjour,

    J'espère que je suis au bon endroit pour poster mon problème que j'ai rencontré concernant le plateau hexagonal. La création d'une fenêtre est faite jusqu'à ce que je n'ai pas réussi. J'ai fait le code que je veux afficher la grille hexagonale dans JPanel, l'erreur n'est pas signalée mais la grille n'affiche pas. Je ne vois pas vraiment pourquoi je ne peux pas l'afficher.

    Voici un bout de 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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    import javax.swing.JPanel;
    import java.awt.Image;
    import java.awt.Graphics;
     
    import java.awt.Polygon;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.awt.Graphics2D;
     
    import javax.swing.JScrollPane;
    import java.awt.BasicStroke;
     
    public class Panneau extends JPanel {
     
    	final static int cote=26;
    	private Image bg;
     
    	private static Point[][] hexSamplePoints; 
    	int Col = 11;
    	int Ligne = 46;
    	Point hovered = null;
    	//Polygon pol;
     
    	int RR = 35;
    	int Oxx = 48;
    	int Oyy = 52;
    	int x[] = {0, 0, 0, 0, 0, 0};
    	int y[] = {0, 0, 0, 0, 0, 0};
     
    	public void paintComponent(Graphics g){
     
    		Tuile t = new Tuile(); => j'ai créé une classe pour charger une image
                    bg = t.chargerImage("map.jpg");
    		g.drawImage(bg,0,0,this);
     
    		BasicStroke bs=new BasicStroke(5);
    		super.paint(arg0);
    		Graphics2D g2d;
     
    		for(int i = 1; i < Ligne; i=i+2) 
    		 { 
    			for(int j = 0; j < Col; j++) 
    			{ 
    				Polygon poly = getHex(Oxx, Oyy, RR);
    				//Polygon poly = getPolygon(i, j); 
    			} 
    			g2d.draw(poly);
    		}
     
     
    		if(hovered!=null){
    			g.setColor(Color.red);
    			g2d.setStroke(bs);
    			Polygon p = getHex(Oxx, Oyy, RR);
    			//Polygon p=getPolygon(hovered.x, hovered.y,cote);
    			g2d.draw(p);
    		}
     
    	}
     
    	public static Point getHex(int Ox, int Oy, int R){
    		for (int j = 0; j < Ligne; j++){
    			for (int i = 0; i < Col; i++){
    				x[0] = Ox - R;
    				y[0] = Oy;
     
    				x[1] = Ox - R/2;
    				y[1] = Oy - R;
     
    				x[2] = Ox + R/2;
    				y[2] = Oy - R;
     
    				x[3] = Ox + R;
    				y[3] = Oy;
     
    				x[4] = Ox + R/2;
    				y[4] = Oy + R;
     
    				x[5] = Ox - R/2;
    				y[5] = Oy + R;
     
    				Ox = Ox + 3*R;
    				System.out.println("inc x : " + Ox);
     
    				g.drawPolygon(x, y, 6);
    			}
     
    			Oy = Oy + R;
    			if (Ox == Oox + R * 3 * Col){
    				Ox = Oox + R + R/2;
    			}
    			else {
    				Ox = Oox;
    			}
    			System.out.println("inc y : " + Oy);
    		}
    	}
    }


    J'ai hésité de faire une méthode getPolygon que getHex :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	public  static Point getPolygon(Point center, double size, int cote){
    		double angle_deg = 60 * cote  + 30;
    		double angle_rad = Math.PI / 180 * angle_deg;
     
    		return new Point(center.x + size * Math.cos(angle_rad), center.y + size * Math.sin(angle_rad));
     
    	}

    Si vous avez d'autres codes à me conseiller, je serai preneuse et merci !

  2. #2
    Modérateur

    Salut,

    Il faudrait nous montrer un code qui compile au moins, parce que là avec ce que tu montres, c'est sûr que ça n'affiche rien, puisque ça n'est même pas exécutable.

    Un premier conseil sur ce que je vois c'est de ne pas charger d'image dans paintComponent, et plus généralement dans les méthodes de dessin. Charge les images une fois pour toute à part, et fait dans la partie affichage uniquement des actions rapides pour limiter le temps d'exécution de cette partie (pour limiter le temps de blocage de l'UI).

    Il peut être préférable, en particulier si le fond est fixe, de dessiner une image (on peut la construire dynamiquement au lancement du programme, exactement de la même manière qu'on dessine dans le fond du composant), et ne dessinant dans paintComponent que ce qui change, ce qui sera plus rapide que de redessiner tous les hexagônes à chaque repaint.

    Exemple rapide en dessinant dynamiquement à chaque repaint:
    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
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    public class HexaDemo extends JPanel {
     
    	private final int diam;
    	private Path2D.Double hex;
    	private double gap;
    	private double shift;
     
    	private Point mouse;
    	private Image image;
     
    	public HexaDemo(int diam, Image image) {
    		setBackground(Color.WHITE);
    		this.image=image;
    		this.diam=diam;
    		hex = new Path2D.Double();
    		double angle = Math.PI/3;
    		double ray=diam/2;
    		gap = 2 * ray * Math.sin(Math.PI/6); // périmètre 2Rn * sin(PI/n) 
    		for(int i=0; i<6; i++) {
    			double x=ray+Math.cos(angle*i)*ray;
    			double y=Math.sin(angle*i)*ray;
    			if( i==0 ) {
    				hex.moveTo(x, y);
    			}
    			else {
    				hex.lineTo(x, y);
    			}
    		}
    		hex.closePath();
    		shift=Math.cos(2*Math.PI/3)*ray-gap;
    		MouseAdapter mouseAdapter = new MouseAdapter() {
    			@Override
    			public void mouseMoved(MouseEvent e) {
    				mouse = e.getPoint();
    				repaint();
    			}
     
    			@Override
    			public void mouseExited(MouseEvent e) {
    				mouse=null;
    				repaint();
    			}
    		};
    		addMouseMotionListener(mouseAdapter);
    		addMouseListener(mouseAdapter);
    	}
     
    	@Override
    	protected void paintComponent(Graphics g) {
    		super.paintComponent(g);
    		Graphics2D g2d = (Graphics2D)g;
    		double offset=0;
    		double h=hex.getBounds2D().getHeight()/2;
    		for(int y=0; y<getHeight()+h; y+=h) {
    			for(int x=0; x<getWidth()+gap; x+=diam+gap ) {
    				Shape shape = AffineTransform.getTranslateInstance(x+offset, y).createTransformedShape(hex);
    				if ( mouse!=null && shape.contains(mouse) ) {
    					g.setColor(Color.YELLOW);
    					g2d.fill(shape);
    					// au besoin pour dessiner une image
    					//Graphics2D saveg2d = (Graphics2D)g2d.create();
    					//saveg2d.clip(shape);
    					// exemple pour une image carrée : saveg2d.drawImage(image,(int)(x+offset),(int)(y-h),(int)hex.getBounds().getWidth(),(int)hex.getBounds().getHeight(),this);
    				}
    				g.setColor(Color.DARK_GRAY);
    				g2d.draw(shape);
    			}
    			if (offset==0) {
    				offset=shift;
    			}
    			else {
    				offset=0;
    			}
    		}
     
    	}
     
    	public static void main(String[] args) throws IOException {
     
    		Image image = ImageIO.read(HexaDemo.class.getResource("suricate.jpg")); // le fichier est placé dans le même dossier que le .java
     
    		JFrame frame = new JFrame("Démo");
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		frame.add(new HexaDemo(40,image));
     
    		frame.setSize(600, 600);
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
     
    	}
     
    }
    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 régulier
    Bonjour,

    Je vous remercie d'avoir pris le temps de répondre à mon problème et aussi de m'indiquer vos codes intéressants. J'ai testé vos codes, la grille hexagonale s'est bien affiché et pour répondre à votre demande, j'ai une classe Main :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    public static void main(String[] args){
    		Fenetre fen = new Fenetre();		
    	}


    Puis j'ai crée une fenêtre :
    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
    class Fenetre extends JFrame {
    	 public Fenetre(){
    		this.setTitle("DemonLord");
    		this.setSize(1300, 950); //longeur et hauteur
    		this.setLocationRelativeTo(null);
    		this.setResizable(false);   
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     
    		//this.setPreferredSize(1300, 950);
     
    		Panneau pan = new Panneau();
    		this.setContentPane(pan); 
    		this.setVisible(true);
     
    	 }
    }


    Pour charger une image que j'ai créé une autre classe :
    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
    public class Tuile {
          public String Image;
     
     
        public Image chargerImage(String nomFic){
    	BufferedImage img = null;
            //Image img = null ;
            File f = new File(nomFic);
            try {
                img = ImageIO.read(f);
            } catch (IOException ex) {
                Logger.getLogger(Tuile.class.getName()).log(Level.SEVERE, null, ex);
            }
            return img ;
        }
    }


    Est-ce que c'est bien cela que vous avez demandé?

    Et pour l'image, je veux bien fixer un fond d'une image. J'ai testé vos codes en modifiant le nom d'image et le seul souci est l'image qui n'affiche pas :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Image image = ImageIO.read(MainTest.class.getResource("nomImage.jpg"));

    Aucun message à signaler et l'exécution est succès sans image Une idée de problème pour ImageIO.read?

  4. #4
    Modérateur

    Citation Envoyé par Zalawy Voir le message

    Est-ce que c'est bien cela que vous avez demandé?
    Non. Le code que tu montrais dans ton message initial ne compile pas ! Pour commencer, il contient cet appel Polygon poly = getHex(Oxx, Oyy, RR);. Or la méthode getHex est définie comme çà : public static Point getHex(int Ox, int Oy, int R){. Elle retourne donc un Point (à priori un java.awt.Point) et poly est déclaré comme Polygon (à priori java.awt.Polygon), deux classes incompatibles !

    Citation Envoyé par Zalawy Voir le message

    Et pour l'image, je veux bien fixer un fond d'une image. J'ai testé vos codes en modifiant le nom d'image et le seul souci est l'image qui n'affiche pas :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    Image image = ImageIO.read(MainTest.class.getResource("nomImage.jpg"));

    Aucun message à signaler et l'exécution est succès sans image Une idée de problème pour ImageIO.read?
    1. As-tu bien mis le fichier nomImage.jpg dans le dossier de HexaDemo.java ?
    2. As-tu décommenté le code qui affiche l'image (lignes 61 à 63 dans mon exemple) :
      Code :Sélectionner tout -Visualiser dans une fenêtre à part
      1
      2
      3
      4
      // au besoin pour dessiner une image
      Graphics2D saveg2d = (Graphics2D)g2d.create();
      saveg2d.clip(shape);
      saveg2d.drawImage(image,(int)(x+offset),(int)(y-h),(int)hex.getBounds().getWidth(),(int)hex.getBounds().getHeight(),this);

      Attention, c'est un exemple simple prévu pour afficher une image carrée, qui affiche l'image dans l’hexagone survolé par la souris. A adapter à tout autre besoin/contexte.


    Le problème avec le chargement d'image dans ton code, ce n'est pas la classe Tuile. J'imagine que le but est qu'elle évolue pour représenter une tuile avec des attributs, d'autres méthodes, etc. C'est le fait que l'accès au fichier est fait dans le code de dessin, lors de l'appel de paintComponent, par un accès disque, donc potentiellement lent, et chaque redessin du panel. Pour peu que tu aies plusieurs tuiles différentes à afficher et ça va faire autant de de chargement de fichiers qui vont ralentir l'affichage et bloquer l'interaction (les deux sont faits dans le même thread, l'Event Dispatch Thread (EDT) : cela peut être particulièrement gênant d'avoir la souris qui se déplace par à-coups).



    Enfin, si tu regardes la différence entre mon code de chargement et le tiens :
    • le tiens utilise un File, donc accède au filesystem
    • le miens utilise une ressource, qui sera distribué avec les .class, dans un jar normalement


    L'avantage du miens est que le programme final pourra être livré en un seul fichier qui se suffit à lui-même, et peut être placé n'importe où selon l'envie de l'utilisateur. Le tiens nécessitera de distribuer les fichiers images à part et a les placer à un endroit bien défini par rapport au jar du programme. En plus, utilisera pourra changer comme il veut les images, ce que tu ne veux pas éventuellement.

    Pour mon exemple, j'ai simplifié en admettant que le fichier image serait dans le dossier du .java, mais tu peux faire un dossier images avec toutes les fichier jpg dedans. Il suffit qu'il soit dans le classpath (et pour accèder à un fichier, par exemple : Image image = ImageIO.read(HexaDemo.class.getResource("/images/tuile_foret_dense.jpg"));)
    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.