Comment puis-je changer JPanel dans un JFrame à la volée?

Pour simplifier, il existe une simple application de swing Java qui consiste en JFrame avec certains composants. L’un des composants est un JPanel qui doit être remplacé par un autre JPanel sur l’action de l’utilisateur.

Alors, quelle est la bonne façon de faire une telle chose? J’ai essayé

panel = new CustomJPanelWithComponentsOnIt(); parentFrameJPanelBelongsTo.pack(); 

mais ça ne marchera pas. Que suggérerais-tu?

Votre cas d’utilisation semble parfait pour CardLayout .

Dans la présentation de la carte, vous pouvez append plusieurs panneaux au même endroit, mais ensuite afficher ou masquer un panneau à la fois.

1) Définition du premier panel:

 JFrame frame=new JFrame(); frame.getContentPane().add(new JPanel()); 

2) Remplacement du panneau:

 frame.getContentPane().removeAll(); frame.getContentPane().add(new JPanel()); 

Notez également que vous devez le faire dans le fil de discussion de l’événement, pour vous assurer que vous utilisez le SwingUtilities.invokeLater ou le SwingWorker.

 frame.setContentPane(newContents()); frame.revalidate(); // frame.pack() if you want to resize. 

Rappelez-vous que Java utilise l’argument “copier la référence par valeur”. Donc, changer une variable ne changera pas les copies de la référence transmise aux autres méthodes.

Notez également que JFrame est très compliqué au nom de la facilité d’utilisation. L’ajout d’un composant ou la définition d’une mise en page (généralement) effectue l’opération sur le volet de contenu. Curieusement, obtenir la mise en page vous donne vraiment le gestionnaire de disposition du cadre.

J’espère que ce morceau de code vous donnera une idée de la modification de jPanels dans un JFrame.

 public class PanelTest extends JFrame { Container contentPane; public PanelTest() { super("Changing JPanel inside a JFrame"); contentPane=getContentPane(); } public void createChangePanel() { contentPane.removeAll(); JPanel newPanel=new JPanel(); contentPane.add(newPanel); System.out.println("new panel created");//for debugging purposes validate(); setVisible(true); } } 

Sur l’action de l’utilisateur:

// tu dois faire quelque chose comme

 myJFrame.getContentPane().removeAll() myJFrame.getContentPane().invalidate() myJFrame.getContentPane().add(newContentPanel) myJFrame.getContentPane().revalidate() 

Vous pouvez ensuite redimensionner votre fenêtre si nécessaire.

Tout dépend de la façon dont il va être utilisé. Si vous souhaitez basculer entre ces deux panneaux, utilisez un CardLayout. Si vous ne faites que passer de la première à la deuxième fois et (et ne pas revenir en arrière), j’utiliserais la suggestion de telcontar et je la remplacerais simplement. Cependant, si le JPanel n’est pas la seule chose dans votre cadre, j’utiliserais remove (java.awt.Component) au lieu de removeAll.

Si vous êtes quelque part entre ces deux cas, il s’agit essentiellement d’un compromis temps-espace. Le CardLayout vous fera gagner du temps mais prendra plus de mémoire en gardant tout ce panneau en mémoire à tout moment. Mais si vous remplacez simplement le panneau lorsque vous en avez besoin et que vous le construisez à la demande, vous n’avez pas besoin de garder ce message, mais cela prend plus de temps pour le changer.

Aussi, vous pouvez essayer un JTabbedPane pour utiliser des tabs à la place (c’est encore plus facile que CardLayout car il gère automatiquement l’affichage / le masquage)

Les autres personnes ont répondu à la question. Je veux vous suggérer d’utiliser un JTabbedPane au lieu de remplacer le contenu. En règle générale, les éléments visuels de votre application doivent disparaître ou être remplacés par d’autres contenus. Certes, il existe des exceptions à chaque règle, et seuls vous et votre communauté d’utilisateurs pouvez décider de la meilleure approche.

J’avais exactement le même problème !! Incroyable !! La solution que j’ai trouvée était la suivante:

  1. Ajouter tous les composants (JPanels) au conteneur;
  2. Utiliser la méthode setVisible (false) pour tous
  3. Sur l’action de l’utilisateur, définissez setVisible (true) sur le panneau que je voulais afficher.
 // Hiding all components (JPanels) added to a container (ex: another JPanel) for (Component component : this.container.getComponents()) { component.setVisible(false); } 
 // Showing only the selected JPanel, the one user wants to see panel.setVisible(true); 

Pas de revalidate (), pas de validate (), pas de CardLayout nécessaire.

La réponse layout.replace () existe uniquement / fonctionne sur le gestionnaire GroupLayout.

D’autres LayoutManagers (CardLayout, BoxLayout, etc.) NE supportent PAS cette fonctionnalité, mais vous obligent d’abord à RemoveLayoutComponent (et ensuite à AddLayoutComponent (back back. :-)).

Je vous suggère d’append les deux panneaux lors de la création de l’image, puis de modifier le panneau visible en appelant setVisible (true / false) sur les deux. Lorsque vous appelez setVisible, le parent sera averti et invité à se repeindre.

 class Frame1 extends javax.swing.JFrame { remove(previouspanel); //or getContentPane().removeAll(); add(newpanel); //or setContentPane(newpanel); invalidate(); validate(); // or ((JComponent) getContentPane()).revalidate(); repaint(); //DO NOT FORGET REPAINT } 

Parfois, vous pouvez faire le travail sans utiliser la revalidation et parfois sans utiliser le repaint.My conseiller d’utiliser les deux.

Problème : mon composant n’apparaît pas après l’avoir ajouté au conteneur.

Vous devez invoquer la revalidation et repeindre après l’ajout d’ un composant avant qu’il n’apparaisse dans votre conteneur.

Source: http://docs.oracle.com/javase/tutorial/uiswing/layout/problems.html

Il suffit d’appeler la méthode pack () après avoir défini le ContentPane , ( java 1.7 , peut-être plus ancien) comme ceci:

 JFrame frame = new JFrame(); JPanel panel1 = new JPanel(); JPanel panel2 = new JPanel(); .... frame.setContentPane(panel1); frame.pack(); ... frame.setContentPane(panel2); frame.pack(); ... 

vous pouvez utiliser la méthode replace d’une mise en page:

 layout.replace(existingComponent, newComponent) 

les composants existants et nouveaux peuvent également être des JPanels.