Java Swing revalidate () vs repaint ()

211

Estoy armando una aplicación Swing donde a menudo quiero reemplazar el contenido de un JPanel. Para hacer esto, llamo removeAll(), luego agrego mi nuevo contenido, luego llamo revalidate().

Sin embargo, estoy descubriendo que el contenido anterior todavía es realmente visible (aunque oscurecido por el contenido nuevo). Si agrego una llamada repaint()además de revalidate(), funciona como se esperaba.

Estoy seguro de que en otras ocasiones he experimentado que solo llamar revalidate()es suficiente.

Básicamente, mi pregunta es: ¿debería tener que llamar a ambas funciones y, si no, cuándo debo llamar a cada una de ellas?

Guillermo
fuente
66
Este tutorial de Oracle dice: "Siempre invoque repintar después de revalidar". Sin embargo, no se proporciona ninguna explicación.
minutos

Respuestas:

154

Necesitas llamar repaint()y revalidate(). El primero le dice a Swing que un área de la ventana está sucia (lo cual es necesario para borrar la imagen de los viejos niños eliminados por removeAll()); este último le dice al administrador de diseño que vuelva a calcular el diseño (que es necesario al agregar componentes). Esto debería hacer que los niños del panel se vuelvan a pintar, pero puede no hacer que el panel lo haga (consulte esto para ver la lista de disparadores de repintado).

En una nota más general: en lugar de reutilizar el panel original, recomendaría construir un nuevo panel e intercambiarlos en el padre.

kdgregory
fuente
1
¿Podría racionalizar por qué construir un nuevo panel es una mejor solución que usar el viejo? :)
Arttu
3
@Arttu: es menos trabajo y, por lo tanto, menos propenso a errores.
kdgregory
86

Cada vez que haga un remove () o removeAll (), debe llamar

  validate();
  repaint();

después de haber completado agregar () 'los nuevos componentes.

Llamar validate () o revalidate () es obligatorio cuando hace un remove () - vea los javadocs relevantes.

Mis propias pruebas indican que repintar () también es necesario. No estoy seguro exactamente por qué.

Noel Grandin
fuente
59

revalidatese llama en un contenedor una vez que se agregan componentes nuevos o se eliminan los viejos. Esta llamada es una instrucción para indicarle al administrador de diseño que reinicie en función de la nueva lista de componentes. revalidateactivará una llamada para volver a pintar lo que el componente cree que son "regiones sucias". Obviamente, no todas las regiones en su JPanelson consideradas sucias por el RepaintManager.

repaintse usa para decirle a un componente que se repinte. A menudo es necesario llamar a esto para limpiar condiciones como la suya.

akf
fuente
5

revalidate()solo solicite diseñar el contenedor, cuando experimente simplemente llamar a revalidate()trabajos, podría ser causado por la actualización de los límites de los componentes secundarios desencadena repaint()cuando sus límites se cambian durante el rediseño. En el caso que mencionó, solo se eliminan los componentes y no se cambian los límites de los componentes, este caso no repaint()se activa "accidentalmente" .

Antony Ng
fuente
-4

sí, debe llamar a repintar (); revalidar(); cuando llama a removeAll (), debe llamar a repintar () y revalidar ()

Som Adhikari
fuente