removeAll no elimina en la siguiente validación?

¿Alguien puede explicar por qué lo siguiente no funciona como espero?

Al presionar el botón ‘should’ debe aparecer la pantalla que solo contiene el JScrollPane (vacío), es decir, el campo de entrada y el botón desaparecerán. Sin embargo, permanecen hasta que el componente se redimensiona …

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); } 

Gracias por tu ayuda. pag.

Al actualizar una GUI visible, el código debería ser:

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

El método revalidate() marca componentes que necesitan ser distribuidos, pero hasta que algo desencadena repaint() no verá ningún cambio. Cambiar el tamaño de la ventana primaria es uno de esos disparadores; el cambio de aplicaciones es otro. En esta versión anterior, tenga en cuenta cómo setSize() en el panel obvia la necesidad de volver a repaint() . Del mismo modo, este ejemplo cambia el diseño en resetGame() .

El artículo Painting in AWT and Swing entra en más detalles.

 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(); } }); } } 

Puede ejecutar panel.repaint() como se especifica en el comentario de @Jeremy, sin embargo, la interfaz de usuario seguirá cambiando cuando cambie el tamaño de la ventana. La razón es que la eliminación de los elementos de JPanel hará que el panel cambie de tamaño. Una operación de repintado no causará que el panel cambie de tamaño hasta que JFrame vuelva a verificar su diseño (como ocurre en el redimensionamiento de una ventana).

Para asegurarse de que el diseño se distribuye correctamente en un cambio, puede llamar a frame.validate() . Esta operación hará que JFrame se revalide a sí mismo y a todos los componentes secundarios, que es la misma operación que se lleva a cabo durante un evento de cambio de tamaño de la ventana. Para ejecutar este método en su código, necesitaría cambiar el JFrame frame a final, es decir,

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