2010-03-22 12 views
2

Voici le code:Pourquoi je ne peux pas ajouter un JPanel à JFrame?

import javax.swing.SwingUtilities; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JLabel; 
import java.awt.event.*; 
import java.awt.*; 

public class GameWindow { 

private String[] players; 
private JFrame frame; 

// Constructor. 
public GameWindow(String[] players) { 
    this.players = players; 
} 

// Start the window in the EDT. 
public void start() { 
    SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
    showWindow(); 
    controller.start(); 
    } 
    }); 
} 

// Defines the general properties of and starts the window. 
public void showWindow() { 
    frame = new JFrame("Game"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setSize(600,400); 
    frame.setVisible(true); 
} 

// The thread controlling changes of panels in the main window. 
private Thread controller = new Thread() { 
    public void run() { 
     frame.add(generatePartnerSelectionPanel()); 
     frame.invalidate(); 
     frame.validate(); 
    } 
}; 

// Generate the panel for the selection of a partner. 
private JPanel generatePartnerSelectionPanel() { 
    JPanel panel = new JPanel(); 
    panel.add(new JLabel("Pleas select a partner:")); 
    return panel; 
} 

} 

je devrais voir « Moyens sélectionner le partenaire » et je ne. Pourquoi?

Je suppose que c'est parce que je ne vois pas d'image de la méthode d'exécution du Thread.

AJOUTÉE:

Peut être que je dois faire toutes les mises à jour dans le fil de distribution d'événements ... Je vais vérifier dès maintenant.

a ajouté 2:

I essayé de modifier le code pour le contrôleur. Il n'a pas aidé:

private Thread controller = new Thread() { 
public void run() { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     frame.getContentPane().add(generatePartnerSelectionPanel()); 
     frame.invalidate(); 
     frame.validate(); 
    } 
     }); 
} 
}; 

3 AJOUTÉE:

OK. Voici la version complète du code (ce qui ne fonctionne pas):

import javax.swing.SwingUtilities; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JLabel; 
import java.awt.event.*; 
import java.awt.*; 

public class GameWindow { 

    private String[] players; 
    private JFrame frame; 

    // Constructor. 
    public GameWindow(String[] players) { 
     this.players = players; 
    } 

    // Start the window in the EDT. 
    public void start() { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       showWindow(); 
       controller.start(); 
      } 
     }); 
    } 

    // Defines the general properties of and starts the window. 
    public void showWindow() { 
     frame = new JFrame("Game"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
     frame.setSize(600,400); 
     frame.setVisible(true); 
    } 

    // The thread controlling changes of panels in the main window. 
    private Thread controller = new Thread() { 
     public void run() { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        frame.getContentPane().add(generatePartnerSelectionPanel()); 
        frame.invalidate(); 
        frame.validate(); 
       } 
      }); 
     } 
    }; 

    // Generate the panel for the selection of a partner. 
    private JPanel generatePartnerSelectionPanel() { 
     JPanel panel = new JPanel(); 
     panel.add(new JLabel("Pleas select a partner:")); 
     return panel; 
    } 

} 

4 AJOUTÉE:

Le code suivant ne fonctionne pas non plus. Par ailleurs, pourquoi devrais-je supprimer invokeLater du start? J'ai besoin de démarrer l'interface graphique dans le fil d'expédition de l'événement et invokelater le fait.

import javax.swing.SwingUtilities; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JLabel; 
import java.awt.event.*; 
import java.awt.*; 

public class GameWindow { 

    private String[] players; 
    private JFrame frame; 

    // Constructor. 
    public GameWindow(String[] players) { 
     this.players = players; 
    } 

    // Start the window in the EDT. 
    public void start() { 
//  SwingUtilities.invokeLater(new Runnable() { 
//   public void run() { 
       showWindow(); 
       controller.start(); 
//   } 
//  }); 
    } 

    // Defines the general properties of and starts the window. 
    public void showWindow() { 
     frame = new JFrame("Game"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
     frame.setSize(600,400); 
     frame.setVisible(true); 
    } 

    // The thread controlling changes of panels in the main window. 
    private Thread controller = new Thread() { 
     public void run() { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        frame.getContentPane().add(generatePartnerSelectionPanel()); 
        frame.invalidate(); 
        frame.validate(); 
       } 
      }); 
     } 
    }; 

    // Generate the panel for the selection of a partner. 
    private JPanel generatePartnerSelectionPanel() { 
     JPanel panel = new JPanel(); 
     panel.add(new JLabel("Pleas select a partner:")); 
     return panel; 
    } 

} 

5 AJOUTÉE:

J'ai résolu le problème.

  1. Dans la classe j'ai eu start et showWindow méthodes. Du programme principal j'ai appelé la mauvaise méthode (showWindow au lieu du start). Donc, je remplace la méthode start (pour éviter les confusions avec le début du thread), puis j'ai appelé startWindow de la classe principale et cela a résolu le problème.
+0

re: votre mise à jour. Avez-vous changé 'start' comme je l'ai suggéré? – Randolpho

+0

Vous devez toujours supprimer l'appel 'invokelater' de votre méthode' start'. – Randolpho

+0

Oui, j'ai supprimé le 'invokeLater'. Le code ne fonctionne toujours pas.En passant, je pense que je ne devrais pas supprimer le 'invokeLater' depuis le début car il démarre l'interface graphique dans le fil d'expédition de l'événement (comme il se doit). – Roman

Répondre

4

Vous créez votre fil de mise à jour de l'appel invokeLater. Ce n'est pas comme ça que vous utilisez invokeLater. invokeLater est pour la mise à jour des composants de l'interface utilisateur à partir d'un thread séparé. Appelez invokeLater, en passant un Runnable qui met à jour vos composants de l'interface utilisateur, de votre fil séparé.

Pour plus d'informations, consultez le JavaDocs

Par exemple:

// Start the window in the EDT. 
public void start() { 
    showWindow(); 
    controller.start(); 
} 

// Defines the general properties of and starts the window. 
public void showWindow() { 
    frame = new JFrame("Game"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   
    frame.setSize(600,400); 
    frame.setVisible(true); 
} 

// The thread controlling changes of panels in the main window. 
private Thread controller = new Thread() { 
    public void run() { 

     // some long running process, I assume, but at 
     // some point you want to update UI: 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       frame.add(generatePartnerSelectionPanel()); 
       frame.invalidate(); 
       frame.validate(); 
      } 
     }); 
    } 
}; 
+0

Vous avez raison. Je suis d'accord que j'ai besoin de mettre à jour les composants de l'interface graphique en utilisant invokeLater. J'ai fait ces changements dans le code (je l'ai également mentionné dans la correction de la question). Mais cela n'a pas résolu le problème. – Roman

+0

Avez-vous changé 'start' comme je l'ai suggéré? – Randolpho

+0

Eh bien, j'ai enlevé 'invokeLater' du' start' et cela n'a pas aidé. De plus, je pense que nous devrions utiliser le 'invokeLater' là. Autant que je sache, l'interface graphique doit être démarrée dans le cas où le thread d'expédition est envoyé et invokeLater le fait. – Roman