Java Swing revalidate () vs repaint ()

211

Je mets en place une application Swing où je veux souvent remplacer le contenu d'un JPanel. Pour ce faire, j'appelle removeAll(), puis j'ajoute mon nouveau contenu, puis j'appelle revalidate().

Cependant, je constate que l'ancien contenu est toujours réellement visible (bien qu'obscurci par le nouveau contenu). Si j'ajoute un appel à repaint()en plus de revalidate(), cela fonctionne comme prévu.

Je suis sûr qu'à d'autres occasions, j'ai expérimenté qu'il suffit d'appeler revalidate().

Donc, fondamentalement, ma question est - dois-je avoir besoin d'appeler les deux fonctions et sinon, quand dois-je appeler chacune d'elles?

William
la source
6
Ce didacticiel d'Oracle indique: "Toujours invoquer repeindre après revalidation". Aucune explication n'est cependant fournie.
mn

Réponses:

154

Vous devez appeler repaint()et revalidate(). Le premier dit à Swing qu'une zone de la fenêtre est sale (ce qui est nécessaire pour effacer l'image des vieux enfants enlevés par removeAll()); ce dernier demande au gestionnaire de disposition de recalculer la disposition (ce qui est nécessaire lors de l'ajout de composants). Cela devrait amener les enfants du panneau à se repeindre, mais pas au panneau lui-même (voir ceci pour la liste des déclencheurs de repeindre).

Sur une note plus générale: plutôt que de réutiliser le panneau d'origine, je recommanderais de créer un nouveau panneau et de les échanger sur le parent.

kdgregory
la source
1
Pourriez-vous rationaliser pourquoi la construction d'un nouveau panneau est une meilleure solution que l'utilisation de l'ancien? :)
Arttu
3
@Arttu - c'est moins de travail, et donc moins sujet aux erreurs.
kdgregory
86

Chaque fois que vous effectuez un remove () ou un removeAll (), vous devez appeler

  validate();
  repaint();

une fois que vous avez terminé d'ajouter () les nouveaux composants.

L'appel de validate () ou revalidate () est obligatoire lorsque vous effectuez un remove () - voir les javadocs pertinents.

Mes propres tests indiquent que repeindre () est également nécessaire. Je ne sais pas exactement pourquoi.

Noel Grandin
la source
59

revalidateest appelé sur un conteneur une fois que de nouveaux composants sont ajoutés ou d'anciens supprimés. cet appel est une instruction pour indiquer au gestionnaire de disposition de réinitialiser en fonction de la nouvelle liste de composants. revalidatedéclenchera un appel pour repeindre ce que le composant pense être des «régions sales». Évidemment, toutes les régions de votre région ne JPanelsont pas considérées comme sales par le RepaintManager.

repaintest utilisé pour dire à un composant de se repeindre. Il arrive souvent que vous deviez l'appeler afin de nettoyer des conditions telles que la vôtre.

akf
la source
5

revalidate()il suffit de demander de mettre en page le conteneur, lorsque vous avez simplement appelé revalidate()works, cela peut être dû à la mise à jour des limites des composants enfants qui déclenche repaint()lorsque leurs limites sont modifiées pendant la remise en page. Dans le cas que vous avez mentionné, seul le composant a été supprimé et aucune limite de composant n'est modifiée, ce cas non repaint()est déclenché "accidentellement" .

Antony Ng
la source
-4

oui vous devez appeler repeindre (); revalider (); lorsque vous appelez removeAll (), vous devez appeler repaint () et revalidate ()

Som Adhikari
la source