J'ai trouvé un exemple dans lequel des boutons sont ajoutés aux panneaux (instances de JPanel
) puis des panneaux sont ajoutés aux conteneurs (instances générées par getContentPane()
) et puis les conteneurs sont, par la construction, inclus dans le JFrame
(les fenêtres).
J'ai essayé deux choses:
Je me suis débarrassé des conteneurs. Plus en détail, j'ai ajouté des boutons à un panneau (instance de JPanel
) puis j'ai ajouté le panneau aux fenêtres (instance de JFrame
). Cela a bien fonctionné.
Je me suis débarrassé des panneaux. Plus en détail, j'ai ajouté des boutons directement au conteneur puis j'ai ajouté le conteneur à la fenêtre (instance de JFrame
).
Donc, je ne comprends pas deux choses.
Pourquoi avons-nous deux mécanismes concurrents pour faire les mêmes choses?
Quelle est la raison d'utiliser des conteneurs en combinaison avec les panneaux (JPanel
)? (Par exemple, pour quoi nous incluons des boutons dans JPanels puis nous incluons JPanels dans les conteneurs). Pouvons-nous inclure JPanel
dans JPanel
? Pouvons-nous inclure un conteneur dans un conteneur?
AJOUTÉ:
Peut-être que l'essence de ma question peut être mise dans une seule ligne de code:
frame.getContentPane().add(panel);
Pourquoi avons-nous mis getContentPane()
entre les deux? J'ai essayé juste frame.add(panel);
et cela fonctionne très bien.
AJOUTÉ 2:
Je voudrais ajouter du code pour être plus clair sur ce que je veux dire. Dans cet exemple, j'utilise uniquement JPane:
import Java.awt.*;
import javax.swing.*;
public class HelloWorldSwing {
public static void main(String[] args) {
JFrame frame = new JFrame("HelloWorldSwing");
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(new JButton("W"), BorderLayout.NORTH);
panel.add(new JButton("E"), BorderLayout.SOUTH);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
Et dans cet exemple, j'utilise uniquement le volet de contenu:
import Java.awt.*;
import javax.swing.*;
public class HelloWorldSwing {
public static void main(String[] args) {
JFrame frame = new JFrame("HelloWorldSwing");
Container pane = frame.getContentPane();
pane.setLayout(new BorderLayout());
pane.add(new JButton("W"), BorderLayout.NORTH);
pane.add(new JButton("E"), BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
Les deux fonctionnent bien! Je veux juste savoir si entre ces deux façons de faire les choses est meilleure (plus sûre).
Ce ne sont pas deux mécanismes concurrents - un JPanel
est unContainer
(juste regardez la hiérarchie des classes en haut de la JPanel javadocs ). JFrame.getContentPane()
renvoie juste un Container
pour placer les Component
s que vous souhaitez afficher dans le JFrame
. En interne, il utilise un JPanel
(par défaut - vous pouvez changer cela en appelant setContentPane()
) Quant à savoir pourquoi il retourne un Container
au lieu d'un JPanel
- c'est parce que vous devriez programmer une interface, pas une implémentation - à ce niveau, tout ce dont vous avez besoin est que vous pouvez ajouter Component
s à quelque chose - et même si Container
est une classe plutôt qu'une interface - elle fournit l'interface nécessaire pour faire exactement cela.
Quant à savoir pourquoi JFrame.add()
et JFrame.getContentPane().add()
font tous deux la même chose - JFrame.add()
est remplacé pour appeler JFrame.getContentPane().add()
. Ce n'était pas toujours le cas - avant JDK 1.5, vous deviez toujours spécifier JFrame.getContentPane().add()
explicitement et JFrame.add()
jetait un RuntimeException
si vous l'appeliez, mais à cause de beaucoup plaintes, cela a été changé dans JDK 1.5 pour faire ce que vous attendez.
Bonne question. J'ai trouvé utile de comprendre que "Swing fournit trois classes de conteneurs de niveau supérieur généralement utiles: JFrame
, JDialog
et JApplet
. ... Par commodité, l'ajout La méthode et ses variantes, remove et setLayout ont été remplacées pour être transmises au contentPane si nécessaire. "— Utilisation de conteneurs de niveau supérieur =
intéressant: jframe.setBackground(color)
ne fonctionne pas pour moi, mais jframe.getContentPane().setBackground(color)
fonctionne.
Je crois que la raison en est que Swing a été construit à partir d'AWT et que Container est un objet AWT de haut niveau. Ce n'est vraiment pas le meilleur choix de conception, car vous ne voulez généralement pas mélanger des objets AWT (lourds) avec Swing (légers).
Je pense que la meilleure façon de le gérer est de toujours lancer le contentPane sur un JPanel.
JPanel contentPanel = (JPanel)aFrame.getContentPane();
L'histoire et la mécanique de ceci sont également discutées en détail dans cet article leepoint . A noter en particulier:
getContentPane()
renvoie un objetContainer
. Ce n'est pas vraiment un simple objetContainer
, mais c'est en fait unJPanel
! Il s'agit d'unContainer
comme conséquence de la hiérarchie. Donc, si nous obtenons le volet de contenu prédéfini, il s'avère qu'il s'agit en fait d'unJPanel
, mais nous ne pouvons vraiment pas profiter des fonctionnalités ajoutées parJComponent
.
et
Ils ont défini les méthodes
add()
dansJFrame
qui appellent simplement les méthodesadd()
correspondantes pour le volet de contenu. Il semble étrange d'ajouter cette fonctionnalité maintenant, d'autant plus que de nombreuses dispositions utilisent plusieurs panneaux imbriqués, vous devez donc toujours être à l'aise pour ajouter directement à unJPanel
. Et tout ce que vous voulez faire avec le volet de contenu ne peut pas être fait via des appels àJFrame
.