Pergunta

Meu principal problema é com o seguinte trecho de código ao configurar um JFrame:

  1. Por que o painel não aparece se eu uso o pack() e como fazer funcionar?

  2. Por que o primeiro requestFocusInWindow() não funciona e qual o princípio para usá-lo?

  3. Por que o gerenciador de layout padrão do JPanel não funciona se eu excluir o setLayout()?


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);
        }
    }
}
} 
Foi útil?

Solução

Sugestões:

  • Chamar setVisible(true) depois ligando pack().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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top