2012-10-24 3 views
2

J'ai des problèmes avec la compréhension du comportement de mon application. Je veux créer une fenêtre simple (1000x700px), divisé en deux parties (250px et 750px largeur respectivement). J'ai essayé le code suivant:Java Swing: problèmes de largeur

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 

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

public class Example extends JFrame 
{ 
    private static final long serialVersionUID = 1L; 

    public Example() 
    { 
     this.setSize(1000, 700); 
     this.setTitle("Example"); 
     this.setResizable(false); 
     this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); 

     JPanel navigation_panel_wrap = new JPanel(); 
     JPanel content_panel_wrap = new JPanel(); 
     navigation_panel_wrap.setPreferredSize(new Dimension(250, 700)); 
     content_panel_wrap.setPreferredSize(new Dimension(750, 700)); 
     content_panel_wrap.setBackground(Color.green); 
     navigation_panel_wrap.setBackground(Color.red); 
     this.getContentPane().add(navigation_panel_wrap); 
     this.getContentPane().add(content_panel_wrap); 
    } 

    public static void main(String[] args) 
    { 
     Example example = new Example(); 
     example.setVisible(true); 
    } 
} 

Comme vous pouvez le voir, je régler manuellement la mise en page gestionnaire pour JFrame (FlowLayout au lieu de BorderLayout avec zéro lacunes horizontales et verticales). Bien sûr, je peux juste utiliser BorderLayout et d'utiliser la méthode add() avec les paramètres BorderLayout.EAST et BorderLayout.WEST, mais je veux comprendre ce qui ne va pas avec FlowLayout. Quand je lance mon application, je reçois le texte suivant (pas de vert JPanel): enter image description here

Si je diminue la largeur, par exemple, content_panel_wrap et fais 744px au lieu de 750px, tout fonctionne correctement. enter image description here Donc la question est - quels sont ces étranges 6 pixels? Je ne suis pas sûr que cette valeur soit constante pour tous les systèmes d'exploitation, donc je veux comprendre son origine.

+2

Voir ce [Q & A] (http://stackoverflow.com/q/7229226/230513). – trashgod

+0

Merci beaucoup, lien très utile. –

Répondre

3

En ce qui concerne votre problème de codes (+1 à @Reimeus) appelant pack() est la solution. selon docs:

les causes de cette fenêtre pour être dimensionnée à la taille préférée et mises en page de ses sous-composants. Si la fenêtre et/ou son propriétaire ne sont pas encore affichables, les deux sont rendus affichables avant de calculer la taille préférée . La fenêtre sera validée après le calcul de la taille préférée .

Conseils:

  • Ne pas inutilement. JFrame étendent
  • Utilisation Event Dispatch Thread lors de la création et la modification des composants de l'interface utilisateur:

    SwingUtilities.invokeLater(new Runnable() { 
        @Override 
        public void run() { 
         // create UI components etc here 
        } 
        }); 
    
  • Dont appel setPreferredSize() plutôt remplacer getPrefferedSize() du composant.
  • Ne pas appeler setSize(...) sur JFrame plutôt appeler JFrame#pack() avant de le définir visible. N'oubliez pas d'appeler JFrame#defaultCloseOperation(..) ou votre thread initial/EDT ne sera pas terminé lorsque JFrame est fermé.

Voici un exemple combinant mes conseils et votre code:

enter image description here

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class Example { 

    private final JFrame frame; 

    public Example() { 
     frame = new JFrame(); 
     frame.setTitle("Example"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//app exited when frame closes 
     frame.setResizable(false); 
     frame.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); 

     JPanel navigation_panel_wrap = new JPanel() { 
      @Override 
      public Dimension getPreferredSize() { 
       return new Dimension(250, 700); 
      } 
     }; 
     JPanel content_panel_wrap = new JPanel() { 
      @Override 
      public Dimension getPreferredSize() { 
       return new Dimension(750, 700); 
      } 
     }; 

     content_panel_wrap.setBackground(Color.green); 
     navigation_panel_wrap.setBackground(Color.red); 

     frame.add(navigation_panel_wrap); 
     frame.add(content_panel_wrap); 
     //pack frame (size components to preferred size) 
     frame.pack(); 
     frame.setVisible(true);//make frame visible 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Example(); 
      } 
     }); 
    } 
} 
+1

Merci pour cette réponse détaillée! Tout est clair, sauf deux choses: 1. _Dont étendre JFrame inutilement._ Je ne devrais pas étendre toutes les classes Swing comme JLabel, JPanel etc. ou simplement JFrame? Et quelle est la raison de faire cela? 2. Quel est l'avantage de surcharger getPrefferedSize() par l'utilisation de setPreferredSize()? –

+1

@ user1600356 +1 c'est un plaisir. En ce qui concerne la question étendue 'JFrame': 1) vous étendez seulement les classes pour ajouter la fonctionnalité 2) une fois que vous étendez' JFrame' vous ne pouvez pas étendre une autre classe dont vous avez besoin ** EFFECTIVEMENT **. En ce qui concerne votre question: * Quel est l'avantage de surcharger getPrefferedSize() par l'utilisation de setPreferredSize()? * Voir ce lien: [Dois-je éviter l'utilisation des méthodes set \ [Preferred | Maximum | Minimum \] dans Java Swing?] (http://stackoverflow.com/q/7229226/1133011) –

4

Il n'y a rien de mal avec FlowLayout mais vous devrez appeler pack() pour que tous les composants soient dimensionnés.