2010-09-09 29 views
3

J'ai l'intention d'implémenter une application Swing qui garde tous ses JComponents dans la fenêtre principale de l'application JFrame. Cela ressemble à du code de procédure maladroit pour donner à tous mes constructeurs JPanel un paramètre faisant référence au JFrame. Donc, certaines recherches ont découvert SwingUtilities.getAncestorOfClass, qui ressemblait à la solution. Mais je ne peux pas comprendre pourquoi il renvoie null quand j'essaie de l'utiliser pour obtenir une référence au JFrame dans mon code JPanel.Java Swing main JFrame: pourquoi SwingUtilities.getAncestorOfClass renvoie null?

Pour vous donner une idée, voici le code pour la principale JFrame, qui crée également un ViewPanel et plonks que dans le JFrame:

import javax.swing.JFrame; 
import javax.swing.SwingUtilities; 

public class SDA { 
    public static void main (String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       SDAMainViewPanel sdaMainViewPanel = new SDAMainViewPanel(); 
       JFrame frame = new JFrame("SDApp"); 
       frame.setSize(400, 400); 
       frame.setContentPane(sdaMainViewPanel); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);      
       frame.setLocationRelativeTo(null);     
       frame.setVisible(true); 
      } 
     }); 
    } 
} 

Voici mon code pour le ViewPanel, qui, lorsque vous appuyez sur le bouton "Try Me", aboutit à une exception NullPointerException, car l'appel à SwingUtilities.getAncestorOfClass pour ViewPanel est un appel nul.

import javax.swing.JPanel; 
import javax.swing.JButton; 
import javax.swing.SwingUtilities; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JFrame; 

public class SDAMainViewPanel extends JPanel { 

    public SDAMainViewPanel() { 
     initComponents(); 
    } 

    private void initComponents() { 
     getAncClass = new JButton("Try me"); 
     // This is null even though there IS an Ancestor JFrame!?!? 
     final JFrame parent = (JFrame)SwingUtilities.getAncestorOfClass(JFrame.class, this); 
     getAncClass.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent ae) {     
       parent.getContentPane().removeAll(); 
      } 
     }); 
     add(getAncClass); 
    } 

    private JButton getAncClass; 
} 

Merci d'avance si vous pouvez répondre à cette question.

Répondre

3

Le constructeur de SDAMainViewPanel appelle initComponents, mais il est appelé avant que sdaMainViewPanel ait été ajouté à un JFrame. Vous pouvez:

  • Appelez initComponents uniquement après l'ajout de SDAMainViewPanel au JFrame.
  • Préparons le cadre parent chaque fois que le ActionListener est appelé:

    public void actionPerformed(ActionEvent ae) { 
        JFrame parent = (JFrame)SwingUtilities.getAncestorOfClass(JFrame.class, SDAMainViewPanel.this); 
        parent.getContentPane().removeAll(); 
    } 
    
+0

Un grand merci. +1 pour l'exactitude des options données. J'espère que cela aidera d'autres gens de Java aussi. – Arvanem