Partage
  • Partager sur Facebook
  • Partager sur Twitter

setPreferredSize ne fonctionne pas au lancement...

Sujet résolu
    15 décembre 2009 à 20:52:39

    Bonjour à vous !! Je viens demander de l'aide aux experts zéros de ce site pour
    un problème sur lequel je suis penché depuis 3 semaine...

    Je suis en train de développer un tetris. J'ai une classe Main, dans laquelle j'ai instancié une fenêtre héritée de JFrame. J'ai fait un contentPan hérité de JPanel.
    Jusque là, pas de problème :D

    Donc dans ce panneau, j'initialise un objet tetris encore hérité d'un JPanel.
    Dans cet objet, j'ai un objet jeu hérité d'un JPanel. C'est le plateau.
    L'objet tetris calcul la taille de l'objet jeu en fonction de sa propre taille.
    Bref, tous fonctionne presque... lorsque je redimensionne la fenêtre, la taille du jeu change et garde les bon rapports.
    Le problème, c'est au lancement : la taille du jeu n'est pas de la bonne taille, c'est juste un petit carré au millieu...

    Je met mon code que j'ai, il me semble, simplifier au maximum pour le problème... :

    import java.awt.GraphicsDevice;
    
    public class Main {
    
    	
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    
    		Fenetre fen = new Fenetre();
    
    		
    	}
    
    }
    

    import java.awt.Dimension;
    import java.awt.DisplayMode;
    import java.awt.GraphicsDevice;
    
    
    import javax.swing.JFrame;
    
    
    
    public class Fenetre extends JFrame {
    	public Panneau panneau;
    	GraphicsDevice myDevice = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
    	
    	public Fenetre(){
    	
    		super();
    		//Définition de la fenêtre et du panneau
    		
    		this.setSize(new Dimension(400,400));
    		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    		//------
    		panneau=new Panneau();
    		this.setContentPane(panneau);
    		//___________________________
    
    		//Finalisation
    		this.setVisible(true);
    		
    	}
    
    }
    


    import java.awt.Dimension;
    
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Graphics;
    import java.awt.GraphicsConfiguration;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.HeadlessException;
    import java.awt.Insets;
    import java.awt.Point;
    import java.awt.TrayIcon;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ComponentEvent;
    import java.awt.event.ComponentListener;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    import com.remij1.tetris.Jeu;
    import com.remij1.tetris.Tetris;
    
    
    public class Panneau extends JPanel{
    
    	//Composant
    	private Tetris tetris;
    	//_______________________
    	
    	
    	public Panneau(){
    		super();
    		BorderLayout bl = new BorderLayout();
    		this.setLayout(bl);
    		
    		//
    		
    		
    		//Initialisation des objets
    		//-----
    		tetris = new Tetris();
    		//_______________________
    
    		//________________________
    		//Ajout des composants
    		this.add(tetris, BorderLayout.CENTER);
    		//___________________
    		
    		
    	}
    	
    	//Méthodes
    
    
    	
    }
    

    package com.remij1.tetris;
    
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.awt.LayoutManager;
    
    import javax.swing.JPanel;
    
    
    
    public class Tetris extends JPanel {
    	private Jeu jeu;
    	
    	public Tetris(){
    		jeu = new Jeu();
    		//-----
    		
    		this.add(jeu);
    	}
    
    	@Override
    	public void paintComponent(Graphics g){
    		calculerTailleJeu();
    	}
    	
    	
    public void calculerTailleJeu(){
    		
    		double rapport = ((double)Jeu.TAILLEY)/((double)Jeu.TAILLEX);
    	
    		if(Math.ceil(this.getWidth()/Jeu.TAILLEX) <= (Math.ceil(this.getHeight()/Jeu.TAILLEY)))
    		{
    			jeu.setTailleCase((int) (Math.ceil((this.getWidth()-20)/Jeu.TAILLEX)));
    		}
    		else
    		{
    			jeu.setTailleCase((int) (Math.ceil((this.getHeight()-20)/Jeu.TAILLEY)));
    		}
    		jeu.setPreferredSize(new Dimension(jeu.getTailleCase()*Jeu.TAILLEX,jeu.getTailleCase()*Jeu.TAILLEY));
    		
    		
    	}	
    
    }
    

    package com.remij1.tetris;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    
    import java.awt.LayoutManager;
    
    import javax.swing.JButton;
    import javax.swing.JPanel;
    
    
    
    
    /*
     * Taille du jeu: TAILLEX, TAILLEY
     * 
     * 
     * Coordonée de la table:
     * 		x horizontal, de gauche à droite
     * 		y vertical, de bas en haut
     */
    
    
    public class Jeu extends JPanel{
    	
    	//Constantes
    	public static int TAILLEX = 10;
    	public static int TAILLEY = 22;
    	//______________________
    	
    	
    	//Objet privé
    	private int tailleCase;
    		
    	//----
    
    	private char[][] table = new char [TAILLEY][TAILLEX];
    	//_______________________
    	
    	
    	
    	//Objet du Pannel
    	
    	public Jeu() {
    		// TODO Auto-generated constructor stub
    		super();
    		
    		//Définition des objets
    		//
    		
    		//_____________________
    		
    				
    	}
    
    	
    	
    	@Override
    	public void paintComponent(Graphics g){
    		g.setColor(Color.ORANGE);
    		g.fillRect(0, 0, this.getWidth(), this.getHeight());
    
    
    	}
    	
    	
    	
    	
    	//Méthode	
    	
    	
    	
    	//GETTERS AND SETTERS
    
    	public int getTailleCase() {
    		return tailleCase;
    	}
    
    
    
    	public void setTailleCase(int tailleCase) {
    		this.tailleCase = tailleCase;
    	}
    
    	
    }
    


    Est-ce que certains d'entre-vous arriveraient à m'expliquer ce qui se passe ??
    Merci
    • Partager sur Facebook
    • Partager sur Twitter
      16 décembre 2009 à 12:24:26

      Ok alors commence par suivre ce schéma :
      @Override
      public void paintComponent(Graphics g) {
         super.paintComponent(g); //faut toujours toujours l'appeler pour que la mécanique de Swing se mette bien en place
        //ici UNIQUEMENT des instruction qui ont besoin de l'objet Graphics g
      }
      


      Autrement dit, calculerTailleJeu() dans paintComponent() n'est pas une bonne idée.
      Alors change la place de ta méthode, et mets l'instruction, et mets l'instruction super.paintComponent().
      Est-ce que ça change quelque chose visuellement ?
      • Partager sur Facebook
      • Partager sur Twitter
        16 décembre 2009 à 20:05:34

        Salut !
        Tous d'abord merci beaucoup pour ta réponse.

        Alors visuellement ya plus rien...

        J'ai mis la commande calculerTailleJeu() à la fin du constructeur de la classe Tetris et rajouté partout les super.paintComponent(g). Je donne les sources de Tetris et Jeu:
        package com.remij1.tetris;
        
        import java.awt.Dimension;
        import java.awt.Graphics;
        import java.awt.GridBagConstraints;
        import java.awt.GridBagLayout;
        import java.awt.Insets;
        import java.awt.LayoutManager;
        
        import javax.swing.JPanel;
        
        
        
        public class Tetris extends JPanel {
        	private Jeu jeu;
        	
        	public Tetris(){
        		jeu = new Jeu();
        		//-----
        		this.add(jeu);
        		
        		//-----
        		calculerTailleJeu();
        		
        	}
        
        	@Override
        	public void paintComponent(Graphics g){
        		super.paintComponent(g);
        	}
        	
        	
        	public void calculerTailleJeu(){
        		
        		double rapport = ((double)Jeu.TAILLEY)/((double)Jeu.TAILLEX);
        	
        		if(Math.ceil(this.getWidth()/Jeu.TAILLEX) <= (Math.ceil(this.getHeight()/Jeu.TAILLEY)))
        		{
        			jeu.setTailleCase((int) (Math.ceil((this.getWidth()-20)/Jeu.TAILLEX)));
        		}
        		else
        		{
        			jeu.setTailleCase((int) (Math.ceil((this.getHeight()-20)/Jeu.TAILLEY)));
        		}
        		jeu.setPreferredSize(new Dimension(jeu.getTailleCase()*Jeu.TAILLEX,jeu.getTailleCase()*Jeu.TAILLEY));
        	
        
        
        	}	
        
        }
        

        package com.remij1.tetris;
        
        import java.awt.Color;
        import java.awt.Dimension;
        import java.awt.Graphics;
        
        import java.awt.LayoutManager;
        
        import javax.swing.JButton;
        import javax.swing.JPanel;
        
        
        public class Jeu extends JPanel{
        	
        	//Constantes
        	public static int TAILLEX = 10;
        	public static int TAILLEY = 22;
        	//______________________
        	
        	
        	//Objet privé
        	private int tailleCase;
        		
        	//----
        
        	private char[][] table = new char [TAILLEY][TAILLEX];
        	//_______________________
        	
        	
        	
        	//Objet du Pannel
        	
        	public Jeu() {
        		// TODO Auto-generated constructor stub
        		super();
        		
        		//Définition des objets
        		//
        		
        		//_____________________
        		
        				
        	}
        
        	
        	
        	@Override
        	public void paintComponent(Graphics g){
        		super.paintComponent(g);
        		//---
        		g.setColor(Color.ORANGE);
        		g.fillRect(0, 0, this.getWidth(), this.getHeight());
        	}
        	
        	
        	
        	
        	//Méthode
        
        
        	
        	
        	
        	
        	//GETTERS AND SETTERS
        
        	public int getTailleCase() {
        		return tailleCase;
        	}
        
        
        
        	public void setTailleCase(int tailleCase) {
        		this.tailleCase = tailleCase;
        	}
        
        		
        	
        
        }
        

        J'ai essayer de résoudre ça... j'ai remarqué que la taille retournée dans calculerTailleJeu (this.getWidth()) = 0 avec un println, ce qui fausse toute la taille... j'ai essayé de remplacer cela par this.getPreferredSize().getWidth() ... pas mieux, retourne une valeur négatif (-10)...

        Mais en tout cas, si je définis la taille dans calculerTailleJeu() par des constantes non calculée, tout fonctionne...

        Une idée ??
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          17 décembre 2009 à 17:42:52

          Salut,

          Et si tu essayes de faire un pack() sur ta frame après l'appel à setPreferedSize() ?

          ++

          Edit : Si tu récupères une taille nulle, revois peut-être ta méthode de calcul.
          • Partager sur Facebook
          • Partager sur Twitter
            17 décembre 2009 à 20:53:46

            Salut !
            Merci de ta réponse !
            Le pack() rend à ma fenêtre une toute petite taille... ce qui est logique puisque la taille des classes Jeu et Tetris sont de 0...
            Avant, lorsque que je calculais la taille dans le paintComponent du Tetris, ça marchait presque... seulement au lancement ça ne marchait pas... donc la méthode de calcule fonctionne... Si là ça fonctionne pas, c'est parce que la taille du JPanel tetris retournée est ridiculement petite... et je me base sur celle-ci pour calculer la taille du Jeu.

            Ce que je ne comprend pas, c'est pourquoi le JPanel tetris ne prend pas toute la fenêtre... normalement, quand on met un JPanel, même vide, dans un autre JPanel dont le layout et géré par borderLayout, il devrait tout occuper, non ??
            Je sais pas si je me suis bien fait comprendre...

            • Partager sur Facebook
            • Partager sur Twitter
              17 décembre 2009 à 21:00:13

              Question comme ça : tu n'aurais pas redéfinis les méthodes getX(), getY(), setX(), ou setY() par hasard ?
              Car si c'est le cas j'ai la réponse à tes misères.

              Sinon, et bien si tu es prêt à me fournir l'intégralité de ton code pour que je constate le problème, je te trouve la solution.
              En effet dur d'avoir le coup d'oeil avec toutes tes classes.
              • Partager sur Facebook
              • Partager sur Twitter
                17 décembre 2009 à 22:39:05

                Salut !!
                Merci beaucoup de t'intéresser à mon problème ! Mais je ne voudrais pas abuser de ton aide...

                Alors non je n'ai pas redéfini ces méthodes...

                http://www.box.net/shared/isluomnxp5
                J'ai mis mon code en entier ici.

                Merci
                • Partager sur Facebook
                • Partager sur Twitter
                  18 décembre 2009 à 0:02:12

                  Ok alors j'avoue que j'ai du mal à suivre ton code.
                  Pourquoi faire un "Panneau" comme contentPane de la JFrame ?
                  Actuellement tu as "l'arborescence" suivante :
                  JFrame
                  <<Panneau
                  <<<<Tetris
                  <<<<<<Jeu

                  où << signifie "contient un".
                  Y'a beaucoup trop d'imbrications désordonnées et non justifiées.

                  J'aurais encore bien des remarques à faire, mais ce soir j'ai pas la force de les énumérer. Si tu fais une recherche sur le forum Java avec comme mot-clef "jeu", tu pourrais y apprendre des choses.

                  En ce qui concerne ton problème, j'te file une solution à court terme.
                  Y'a effectivement un problème au niveau de ta méthode de calcul : tu demandes la taille du JPanel Tetris alors que tu n'as pas fait setSize() dessus avant. Donc getWidth() renverra forcément 0.
                  Donc une solution est d'appliquer setSize() à ton objet...

                  Enfin, bon courage.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Anonyme
                    18 décembre 2009 à 13:05:46

                    Une chose bonne à savoir c'est que tant qu'un composant n'a pas été montré à l'écran, ses dimensions sont nulles. Ça peut poser pas mal de problèmes à l'initialisation notamment. C'est pour ça qu'en général je ne me sers que de la preferedSize.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      18 décembre 2009 à 17:47:32

                      Merci !
                      elmh:
                      Alors le panneau c'était pour pouvoir modifier le paintComponent()... que finalement je n'utilise pas finalement.
                      Sinon, normalement, le JPanel Tetris était censé prendre toute la place disponible. Puis, la taille du jeu défini en fonction de la taille de Tetris. Comme ça, je n'avait pas à me soucier de la taille exacte que devait avoir le plateau du jeu pour ne pas déformer les carrés. Je définis la taille du Tetris, le jeu se redimensionne au mieux à l'intérieur...
                      Sinon, peut-être que beaucoup de classe te semble inutiles, mais j'ai enlever une bonne partie du code complet, j'ai isolé mon problème... Mais c'est vrai que le JPanel panneau est sans doute inutile... je corrigerait ça.
                      Je vais utiliser ta solution... peut-être qu'un jour je comprendrais tous seul :p
                      A BZ:
                      Ouf c'est vrai que c'est embêtant... Mais je vais utiliser setSize() sur Tetris pour l'instant...

                      Merci
                      • Partager sur Facebook
                      • Partager sur Twitter

                      setPreferredSize ne fonctionne pas au lancement...

                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                      • Editeur
                      • Markdown