JFrame pack() e requestFocus() não estão funcionando
-
21-12-2019 - |
Pergunta
Meu principal problema é com o seguinte trecho de código ao configurar um JFrame
:
Por que o painel não aparece se eu uso o
pack()
e como fazer funcionar?Por que o primeiro
requestFocusInWindow()
não funciona e qual o princípio para usá-lo?Por que o gerenciador de layout padrão do
JPanel
não funciona se eu excluir osetLayout()
?
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);
}
}
}
}
Solução
Sugestões:
- Chamar
setVisible(true)
depois ligandopack()
.Faz sentido, não é? - O BorderLayout dirá ao MyDrawPanel para preencher o contêiner p, já que o componente está sendo adicionado de forma padrão (ou seja, BorderLayout.CENTER), e é assim que o BorderLayout funciona.
- FlowLayout não preenche o contêiner, mas permite que os componentes sejam dimensionados de acordo com seus preferidosSizes.
- Não misture Swing com componentes AWT.ou seja, não use Painéis, mas sim JPanels.
- requestFocus funciona apenas em componentes focáveis exibidos.
- Melhor usar Key Bindings do que KeyListeners.
- É melhor evitar definir os tamanhos de qualquer coisa, se possível.
Com base no seu novo código, seu problema é porque você está ligando setSize()
.A maioria dos gerenciadores de layout não respeita isso, mas sim o tamanho preferido.Se o seu desenho JPanel precisa ser tão grande, faça-o assim.Por exemplo, tente:
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);
}
}
Observe também que request focus faz funciona se o componente for focável:
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();
Mas observe também que KeyListeners devem ser evitados.Em vez disso, use combinações de teclas.