Comment changer JPanel à l'intérieur d'un JFrame à la volée?

pour simplifier, il y a une application java swing simple qui se compose de JFrame avec quelques composants. Un des composants est un JPanel qui est destiné à être remplacé par un autre JPanel sur l'action de l'utilisateur.

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

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

mais ça ne marchera pas. Que suggérez-vous?

39
demandé sur Andrew Thompson 2008-10-20 15:53:41

14 réponses

votre cas d'utilisation, semble parfait pour CardLayout.

dans la mise en page de la carte, vous pouvez ajouter plusieurs panneaux au même endroit, mais ensuite afficher ou cacher, un panneau à la fois.

49
répondu Swapnonil Mukherjee 2008-10-20 14:00:58

1) Paramétrage du premier panneau:

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

notez aussi que vous devez faire ceci dans le Thread de L'événement, pour vous assurer que cela utilise le SwingUtilities.invokeLater ou SwingWorker

24
répondu Telcontar 2008-10-20 14:05:29
frame.setContentPane(newContents());
frame.revalidate(); // frame.pack() if you want to resize.

Rappelez-vous, Java utiliser " copier la référence par la valeur de l'argument de passage. Ainsi changer une variable ne changera pas des copies de la référence passée à d'autres méthodes.

notez Aussi JFrame est très déroutant au nom de la convivialité. Ajouter un composant ou définir une mise en page (habituellement) effectue l'opération sur le volet de contenu. Curieusement, l'obtention de la mise en page vous donne vraiment l'image du gestionnaire de présentation.

17
répondu Tom Hawtin - tackline 2008-10-20 12:31:26

espérons que ce morceau de code vous donne une idée de changer jPanels à l'intérieur d'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);
        }
}
6
répondu giannis christofakis 2012-12-01 23:25:29

Sur l'action de l'utilisateur:

// que vous avez à faire quelque chose le long des lignes de

myJFrame.getContentPane().removeAll()
myJFrame.getContentPane().invalidate()

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

alors vous pouvez redimensionner votre wndow au besoin.

5
répondu ShawnD 2008-10-21 15:12:16

tout dépend de comment sa va être utilisé. Si vous souhaitez basculer entre ces deux panneaux, puis utilisez un CardLayout. Si vous passez seulement du premier au deuxième une fois et (et ne revenez pas en arrière) alors j'utiliserais telcontarla suggestion et il suffit de les remplacer. Si le Composite n'est pas la seule chose dans votre cadre, je voudrais utiliser enlever(java.awt.Composant) au lieu de removeAll.

Si vous êtes quelque part entre ces deux cas, c'est en fait un espace-temps du compromis. Le CardLayout vous fera gagner du temps, mais prendra plus de mémoire en ayant à garder cet autre panneau entier en mémoire à tout moment. Mais si vous remplacez le panneau au besoin et que vous le construisez à la demande, vous n'avez pas à garder ce meory à portée de main, mais il faut plus de temps pour changer.

vous pouvez aussi essayer un JTabbedPane pour utiliser des onglets à la place (c'est encore plus facile que CardLayout car il gère automatiquement l'affichage/la dissimulation)

3
répondu luke 2017-05-23 12:09:17

les autres personnes ont répondu à la question. Je vous suggère d'utiliser un JTabbedPane au lieu de remplacer le contenu. En règle générale, il est mauvais de faire disparaître des éléments visuels de votre application ou de les remplacer par d'autres contenus. Il y a certainement des exceptions à chaque règle, et seuls vous et votre communauté d'utilisateurs pouvez décider de la meilleure approche.

1
répondu James A Wilson 2008-10-20 13:11:19

j'avais exactement le même problème!! Increadible!! La solution que j'ai trouvée était:

  1. ajouter tous les composants (JPanels) au conteneur;
  2. en utilisant la méthode setVisible(false) pour tous;
  3. sur l'action de l'utilisateur, paramétrer setVisible (true) au panneau que je voulais montrer.
// 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 valider(), pas de CardLayout nécessaire.

1
répondu Gabriel 2012-11-21 19:29:53

La mise en page.replace () answer n'existe que sur le Gestionnaire GroupLayout.

les autres managers de Layout (CardLayout, BoxLayout etc) ne supportent pas cette fonctionnalité, mais vous demandent d'abord de RemoveLayoutComponent( et ensuite AddLayoutComponent( retour en arrière. :-) [Mise au point]

1
répondu Warren K 2015-09-11 02:59:12

je vous suggère d'ajouter les deux panneaux lors de la création du cadre, puis de changer le panneau visible en appelant setVisible(true/false) sur les deux. En appelant setVisible, le parent sera avisé et invité à se repeindre.

0
répondu Riduidel 2008-10-20 13:09:15
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 la repeindre.Je conseille d'utiliser les deux.

0
répondu giannis christofakis 2012-02-28 15:27:53

Problème: Mon composant n'apparaît pas après que j'ai ajouté au conteneur.

Vous avez besoin d'invoquer revalider et repeindre après ajout de composant avant, il s'affichera dans votre conteneur.

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

0
répondu Arthur Ronald 2012-04-23 10:11:57

il suffit d'appeler la méthode pack () après avoir réglé le ContentPane, (java 1.7, peut-être plus) comme ceci:

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

frame.setContentPane(panel2);
frame.pack();
...
0
répondu Dudu 2012-10-05 12:14:23

Vous pouvez utiliser la méthode replace d'un layout:

layout.replace(existingComponent, newComponent)

Les composants existants et nouveaux peuvent aussi être JPanels.

-1
répondu user221678 2015-08-05 14:34:21