removeAll não remover no próximo validar?

Alguém pode explicar por que o seguinte não funciona como eu esperava?

Pressionar o botão ‘should’ deve resultar no display contendo apenas o (vazio) JScrollPane, ou seja, o campo de input e o botão devem desaparecer. No entanto, eles permanecem até o componente ser redimensionado …

public static void main(String[] args) { JFrame frame = new JFrame("test"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); final JPanel panel = new JPanel(); Container cp = frame.getContentPane(); cp.setLayout(new FlowLayout()); cp.add(new JScrollPane(panel)); Component textField = new JTextField("i am input"); JButton button = new JButton(new AbstractAction("i am pressy") { @Override public void actionPerformed(ActionEvent e) { // this is already on the EDT panel.removeAll(); panel.revalidate(); } }); panel.setLayout(new FlowLayout()); panel.add(textField); panel.add(button); frame.pack(); frame.setVisible(true); } 

Obrigado pela ajuda. p.

Ao atualizar uma GUI visível, o código deve ser:

 panel.revalidate(); panel.repaint(); // sometimes needed, this appears to be one of them 

O método revalidate() marca os componentes que precisam ser dispostos, mas até que algo acione repaint() você não verá nenhuma alteração. Redimensionar a janela pai é um desses gatilhos; alternar aplicativos é outra. Nesta versão anterior, observe como setSize() no painel elimina a necessidade de repaint() . Da mesma forma, este exemplo altera o layout em resetGame() .

O artigo Pintura em AWT e Swing entra em mais detalhes.

 import java.awt.EventQueue; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.WindowConstants; /** @see https://stackoverflow.com/questions/5812002 */ public class RevalidateTest { private static JPanel panel = new JPanel(); // default FlowLayout private static JTextField text = new JTextField("Text field"); private static JButton clear = new JButton(new AbstractAction("Clear") { @Override public void actionPerformed(ActionEvent e) { panel.removeAll(); panel.add(reset); panel.revalidate(); panel.repaint(); } }); private static JButton reset = new JButton(new AbstractAction("Reset") { @Override public void actionPerformed(ActionEvent e) { panel.removeAll(); panel.add(text); panel.add(clear); panel.revalidate(); panel.repaint(); } }); static void createAndShowGUI() { JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); panel.add(text); panel.add(clear); frame.add(panel); // default BorderLayout center frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } } 

Você pode executar panel.repaint() conforme especificado no comentário de @Jeremy, no entanto, a interface do usuário ainda será alterada quando você resize a janela. O motivo é que a remoção dos elementos do JPanel fará com que o painel seja redimensionado. Uma operação de repintura não fará com que o painel seja redimensionado até que o JFrame verifique novamente seu layout (como acontece em um redimensionamento de janela).

Para se certificar de que o layout está corretamente disposto em uma alteração, você pode chamar frame.validate() . Essa operação fará com que o JFrame se revalidate e todos os componentes filhos, que é a mesma operação que está ocorrendo durante um evento de redimensionamento de janela. Para executar este método em seu código você precisaria mudar o JFrame frame para final, ou seja,

 final JFrame frame = new JFrame("test");