6 votes

Pourquoi mon jscrollpane entraîne-t-il des appels de peinture étranges dans java swing ?

J'ai une routine qui dessine un graphique incroyablement grand à l'intérieur d'un volet de défilement. Il est trop grand pour être dessiné avant d'être ajouté au volet de défilement - les besoins en mémoire seraient de plusieurs gigaoctets.

En raison de la taille du graphique, je rends le graphique dans la méthode paint de l'enfant du volet de défilement. Cela fonctionne bien, cependant je remarque que chaque fois qu'une barre de défilement est déplacée, ma routine de peinture est appelée deux fois - une fois avec un rectangle de rognage égal à la zone non recouverte défilée, et une deuxième fois avec le rectangle de rognage égal aux dimensions du portail.

Par exemple, si mon portail a pour dimensions 245x195 et que je fais défiler de 3 pixels vers le bas, ma routine de peinture est appelée avec g.getClipBounds() défini comme suit :

java.awt.Rectangle[x=0,y=195,width=245,height=3]
java.awt.Rectangle[x=0,y=3,width=245,height=195]

... parce que je rends dans la routine de peinture, cela provoque du scintillement (je fais mes calculs aussi vite que possible, mais il y a un petit délai je suppose). Questions :

  1. Est-ce que quelqu'un sait comment empêcher le deuxième appel de peinture ? C'est juste le b.a.-ba des JScrollPane que je fais ici - j'ai un composant, je l'ajoute au volet de défilement, j'ajoute le volet de défilement à un composant parent. Vous pouvez voir ce comportement même dans la première démo de défilement d'image sur le tutoriel swing.

  2. Si la réponse à la question n°1 est 'non' : est-ce que quelqu'un peut penser à une bonne façon de gérer cela ? Devrais-je peindre sur une sorte de tampon d'image, suivre les appels de peinture récents et copier l'image quand c'est possible ? Je ne peux pas imaginer que cela soit beaucoup plus rapide que le re-rendu, mais toute idée est appréciée :-)

4voto

colithium Points 6604

Je suis tombé sur ce problème dans le monde du .NET. Le double buffering devrait résoudre votre problème.

Si vous effectuez un rendu directement sur une surface affichée à l'écran, vous n'avez aucun contrôle sur le moment où l'affichage se produit réellement. En général, ce qui se passe est le suivant : vous commencez le rendu, l'image non encore terminée est affichée à l'écran, vous terminez le rendu, et ensuite cela est enfin montré à l'écran.

Si vous commencez votre logique de rendu en effaçant sur une couleur de fond, cela ressemblera à un flash. Le double buffering empêche cela car il affiche toujours à partir d'un rendu terminé. Le pire qui puisse arriver est un léger "déchirement" mais ce n'est perceptible que dans des animations qui changent rapidement.

Même si vous ne voulez rendre qu'une partie d'une image gigantesque, vous pouvez toujours utiliser cette technique. Rend simplement ce dont vous avez besoin sur une surface hors écran (qui est de la taille de la portion visible désirée). Et ensuite, lorsque vous avez terminé, dessinez l'image entière sur votre surface d'affichage en un seul coup.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X