JFrame pack() et requestFocus() ne fonctionnent pas
-
21-12-2019 - |
Question
Mon principal problème concerne le morceau de code suivant lors de la configuration d'un JFrame
:
Pourquoi le panneau ne s'affiche pas si j'utilise le
pack()
et comment le faire fonctionner ?Pourquoi le premier
requestFocusInWindow()
ne fonctionne pas et quel est le principe pour l'utiliser ?Pourquoi le gestionnaire de mise en page par défaut de
JPanel
ne fonctionne pas si je supprime lesetLayout()
?
public class SoundGUI extends KeyAdapter{
public static void main(String[] args) {
SoundGUI sGUI = new SoundGUI();
sGUI.setUp();
}
public void setUp () {
JFrame frame = new JFrame ("Key test");
frame.setSize (1000, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible (true);
Panel p = new Panel ();
p.setLayout(new BorderLayout());//why this sentence is necessary FlowLayout doesn't fill the container but rather lets components size to their preferredSizes.
p.addKeyListener (this);
p.requestFocusInWindow();//it's useless here
//requestFocus only works on focusable components that are displayed.
MyDrawPanel dp = new MyDrawPanel();
dp.setBackground(Color.darkGray);
JLabel test = new JLabel("a trial");
JButton t = new JButton("b");
dp.add(t);
dp.add (test);
p.add (dp);
frame.getContentPane().add(p);
p.requestFocusInWindow();
//frame.pack();//why it doesn't work
//frame.setVisible(true);
}
class MyDrawPanel extends JPanel {
public void paintComponent (Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.white);
for (int i = 0; i < 1000; i += 42) {
g2.fill3DRect(i,100 ,20 ,80 ,true);
}
g2.setColor(Color.black);
for (int i = 21; i < 1000; i += 42) {
g2.fill3DRect(i,100 ,20 ,80 ,true);
}
}
}
}
La solution
Suggestions:
- Appel
setVisible(true)
après appelpack()
.C'est logique, n'est-ce pas ? - BorderLayout dira à MyDrawPanel de remplir le conteneur p, puisque le composant est ajouté par défaut (c'est-à-dire BorderLayout.CENTER), et c'est ainsi que fonctionne BorderLayout.
- FlowLayout ne remplit pas le conteneur mais laisse plutôt les composants redimensionner à leurs tailles préférées.
- Ne mélangez pas Swing avec des composants AWT.c'est-à-dire, n'utilisez pas de panneaux, mais utilisez plutôt JPanels.
- requestFocus ne fonctionne que sur les composants pouvant être focalisés qui sont affichés.
- Mieux vaut utiliser des liaisons de touches que des KeyListeners.
- Mieux vaut éviter de définir la taille de quoi que ce soit si possible.
D'après votre nouveau code, votre problème est dû au fait que vous appelez setSize()
.La plupart des gestionnaires de mise en page ne respectent pas cela mais plutôt la taille préférée.Si votre dessin JPanel doit être si grand, faites-le.Par exemple, essayez :
class MyDrawPanel extends JPanel {
private static final int PREF_W = 1000;
private static final int PREF_H = 300;
public void paintComponent(Graphics g) {
super.paintComponent(g); //!! ******** don't forget this!!! *********
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.white);
for (int i = 0; i < 1000; i += 42) {
g2.fill3DRect(i, 100, 20, 80, true);
}
g2.setColor(Color.black);
for (int i = 21; i < 1000; i += 42) {
g2.fill3DRect(i, 100, 20, 80, true);
}
}
// the getPReferredSize will make this JPanel preferentially be this size
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
}
Notez également que le focus de la demande fait fonctionne si le composant est focalisable :
JPanel p = new JPanel(); //!! This should be a JPanel, not a Panel
p.setFocusable(true); //!! This is needed
p.setLayout(new BorderLayout());
p.addKeyListener(this);
p.requestFocusInWindow();
Mais notez également que les KeyListeners doivent être évités.Utilisez plutôt les liaisons de touches.