Java Swing revalidate () vs repaint ()

211

Ich stelle eine Swing-Anwendung zusammen, in der ich häufig den Inhalt eines JPanel ersetzen möchte. Dazu rufe ich an removeAll(), füge meinen neuen Inhalt hinzu und rufe dann an revalidate().

Ich stelle jedoch fest, dass der alte Inhalt tatsächlich noch sichtbar ist (obwohl er durch den neuen Inhalt verdeckt wird). Wenn ich einen Anruf hinzuzufügen , repaint()zusätzlich zu revalidate(), es funktioniert wie erwartet.

Ich bin mir sicher, dass ich bei anderen Gelegenheiten erlebt habe, dass revalidate()es ausreicht , nur anzurufen .

Meine Frage lautet also im Grunde: Soll ich beide Funktionen aufrufen müssen und wenn nicht, wann soll ich jede aufrufen?

Wilhelm
quelle
6
In diesem Tutorial von Oracle heißt es: "Repaint nach erneuter Validierung immer aufrufen". Es wird jedoch keine Erklärung gegeben.
Minuten

Antworten:

154

Sie müssen anrufen repaint()und revalidate(). Ersteres sagt Swing, dass ein Bereich des Fensters schmutzig ist (was notwendig ist, um das Bild der alten Kinder zu löschen, die von entfernt wurden removeAll()); Letzteres weist den Layout-Manager an, das Layout neu zu berechnen (was beim Hinzufügen von Komponenten erforderlich ist). Dies sollte dazu führen , Kinder der Platte neu zu zeichnen, kann aber nicht dazu führen , das Panel selbst , dies zu tun (siehe dies für die Liste des Repaint Trigger).

Allgemeiner gesagt: Anstatt das ursprüngliche Panel wiederzuverwenden, würde ich empfehlen, ein neues Panel zu erstellen und es beim übergeordneten Panel auszutauschen.

kdgregory
quelle
1
Können Sie erklären, warum das Erstellen eines neuen Panels eine bessere Lösung ist als das Verwenden des alten? :)
Arttu
3
@Arttu - es ist weniger Arbeit und daher weniger fehleranfällig.
kdgregory
86

Jedes Mal, wenn Sie remove () oder removeAll () ausführen, sollten Sie aufrufen

  validate();
  repaint();

Nachdem Sie das Hinzufügen () der neuen Komponenten abgeschlossen haben.

Das Aufrufen von validate () oder revalidate () ist obligatorisch, wenn Sie remove () ausführen - siehe die entsprechenden Javadocs.

Meine eigenen Tests zeigen, dass repaint () ebenfalls notwendig ist. Ich weiß nicht genau warum.

Noel Grandin
quelle
59

revalidatewird für einen Container aufgerufen, sobald neue Komponenten hinzugefügt oder alte entfernt wurden. Dieser Aufruf ist eine Anweisung, den Layout-Manager anzuweisen, basierend auf der neuen Komponentenliste zurückzusetzen. revalidatelöst einen Aufruf aus, um neu zu malen, was die Komponente für "schmutzige Regionen" hält. Offensichtlich werden nicht alle Regionen auf Ihrer Seite JPanelvon der als schmutzig angesehen RepaintManager.

repaintwird verwendet, um eine Komponente anzuweisen, sich selbst neu zu streichen. Es ist häufig der Fall, dass Sie dies aufrufen müssen, um Bedingungen wie Ihre zu bereinigen.

akf
quelle
5

revalidate()Fordern Sie einfach das Layout des Containers an. Wenn Sie revalidate()festgestellt haben, dass einfach Aufrufe ausgeführt werden , kann dies durch die Aktualisierung der untergeordneten Komponentengrenzen verursacht werden, die ausgelöst werden, repaint()wenn ihre Grenzen während des erneuten Layouts geändert werden. Im Fall , dass Sie erwähnten, nur Komponente entfernt und keine Komponente Grenzen verändert wird , ist dieser Fall nicht repaint()ist „versehentlich“ ausgelöst.

Antony Ng
quelle
-4

Ja, Sie müssen repaint () aufrufen. revalidate (); Wenn Sie removeAll () aufrufen, müssen Sie repaint () und revalidate () aufrufen.

Som Adhikari
quelle