Java Swing revalidate () vs repaint ()

211

Przygotowuję aplikację Swing, w której często chcę zastąpić zawartość JPanel. Aby to zrobić, dzwonię removeAll(), a następnie dodaję nową treść, a następnie dzwonię revalidate().

Jednak stwierdzam, że stara treść jest nadal faktycznie widoczna (choć zasłonięta przez nową treść). Jeśli dodam połączenie repaint()do revalidate(), działa to zgodnie z oczekiwaniami.

Jestem pewien, że przy innych okazjach doświadczyłem, że wystarczy zadzwonić revalidate().

Więc w zasadzie moje pytanie brzmi - czy powinienem wywoływać obie funkcje, a jeśli nie, to kiedy mam wywoływać każdą z nich?

William
źródło
6
W tym samouczku Oracle napisano: „Zawsze wywołuj odmalowanie po ponownej walidacji”. Nie podano jednak żadnego wyjaśnienia.
min.

Odpowiedzi:

154

Musisz zadzwonić repaint()i revalidate(). Ten pierwszy mówi Swingowi, że część okna jest brudna (co jest konieczne, aby usunąć zdjęcie starych dzieci usuniętych przez removeAll()); ten ostatni instruuje menedżera układu, aby ponownie obliczył układ (co jest konieczne przy dodawaniu komponentów). Powinno to spowodować dzieci z panelu do odświeżenia, ale nie może powodować sama płyta to zrobić (patrz to na liście wyzwalaczy przemalować).

Mówiąc bardziej ogólnie: zamiast ponownie używać oryginalnego panelu, zaleciłbym zbudowanie nowego panelu i zamianę go w obiekcie nadrzędnym.

kdgregory
źródło
1
Czy możesz zracjonalizować, dlaczego zbudowanie nowego panelu jest lepszym rozwiązaniem niż korzystanie ze starego? :)
Arttu
3
@ Arttu - to mniej pracy, a zatem mniej podatne na błędy.
kdgregory
86

Za każdym razem, gdy wykonujesz remove () lub removeAll (), powinieneś wywołać funkcję

  validate();
  repaint();

po zakończeniu dodawania () nowych komponentów.

Wywołanie validate () lub revalidate () jest obowiązkowe, gdy wykonujesz remove () - zobacz odpowiednie javadocs.

Moje własne testy wskazują, że konieczne jest również odmalowanie (). Nie jestem pewien dokładnie, dlaczego.

Noel Grandin
źródło
59

revalidatejest wywoływany w kontenerze po dodaniu nowych składników lub usunięciu starych. to wywołanie jest instrukcją informującą menedżera układu o konieczności zresetowania na podstawie nowej listy komponentów. revalidatewywoła wezwanie do odmalowania tego, co składnik uważa za „brudne regiony”. Oczywiście nie wszystkie regiony w twoim JPanelsą uważane za brudne przez RepaintManager.

repaintsłuży do informowania komponentu o konieczności odmalowania. Często zdarza się, że musisz to nazwać, aby oczyścić takie warunki, jak twoje.

akf
źródło
5

revalidate()po prostu prośba o rozmieszczenie kontenera, gdy doświadczyłeś po prostu wywołania revalidate()działa, może to być spowodowane aktualizacją granic komponentów potomnych, które powodują zmianę repaint()ich granic podczas zmiany układu. W przypadku, o którym wspomniałeś, tylko komponent został usunięty i nie zostały zmienione żadne granice komponentu, ten przypadek nie repaint()jest uruchamiany „przypadkowo” .

Antony Ng
źródło
-4

tak, musisz wywołać repaint (); revalidate (); kiedy wywołasz removeAll (), musisz wywołać repaint () i revalidate ()

Som Adhikari
źródło