2009-07-22 10 views
6

J'ai ce JTextPane (enveloppé dans un JScrollPane) qui est soutenu par un HTMLEditorKit. Le contenu du JTextPane est un code HTML simple avec des images (fichiers locaux) incorporées à l'aide de balises img. Le problème est que lorsque vous chargez le JTextPane, il faut une fraction de seconde pour charger, puis il apparaît avec la barre de défilement au bas de la page. Si je fais:Définition de la barre de défilement sur un JScrollPane

JTextPane text = new JTextPane(); 
JScrollPane scroll = new JScrollPane(text); 
// do some set up... 
scroll.getVerticalScrollBar().setValue(0); 

il met la barre de défilement momentanément et puis un autre thead (sans doute qui est responsable du chargement des images) vient et frappe la barre de défilement vers le bas. J'ai essayé d'ajouter:

((AbstractDocument)text.getDocument()).setAsynchronousLoadPriority(-1); 

mais cela ne l'a pas résolu. Y at-il un moyen d'obtenir un événement de text.getDocument() ou text qui m'avertira quand le volet est fini de charger afin que je puisse définir la barre de défilement alors? L'alternative est que j'ai mis en place un autre thread à attendre une seconde ou deux, puis définir la barre de défilement, mais c'est un mauvais hack.

Vos suggestions?

Répondre

20

Avez-vous essayé d'utiliser invokeLater?

final JScrollPane scroll = new JScrollPane(text); 
javax.swing.SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
     scroll.getVerticalScrollBar().setValue(0); 
    } 
}); 

Si cela ne fonctionne pas, creuser dans les vues d'image est assez difficile, donc ma prochaine étape serait de retrouver la raison pour laquelle la barre de défilement est en train de changer:

scroll.setVerticalScrollbar(new JScrollBar() { 
    public void setValue(int value) { 
     new Exception().printStackTrace(); 
     super.setValue(value); 
    } 
}); 

Vous pouvez également utiliser un débogueur dans la méthode setValue() au lieu de simplement imprimer la trace de la pile.

+1

La première solution fonctionne, merci. Pourquoi sur Terre n'y at-il pas une méthode pour régler ceci sans avoir à appeler SwingUtilities? –

+3

Aucune idée. Je pense que la façon dont il est conçu est que vous devez créer le JScrollPane, l'ajouter à l'écran, et _then_ définir la valeur. Cela n'a aucun sens pour moi. – Spyder

0

Est-ce que votre application est threadée par hasard? Si c'est le cas, vous pouvez demander une liste des threads en cours d'exécution et être averti lorsqu'ils terminent, puis définir la valeur de la barre de défilement. Est-ce une option?

Ou vous pouvez fournir un ImageObserver à chaque image chargée et définir la position de la barre de défilement lorsque toutes les images sont chargées?

+1

applications Swing comptent sur un thread appelé thread Dispatch d'événements pour contrôler toutes les actions GUI. Vous pouvez contourner cela si vous en avez besoin, mais tout le travail que je fais maintenant est sur le fil d'expédition d'événement. Cela pourrait être considéré comme une option, mais est probablement tout aussi mauvaise que ce que j'ai proposé dans ma question. Je vais le garder à l'esprit cependant. – twolfe18

+0

le ImageObserver pourrait fonctionner alors ... –

1

Voici résolu le problème pour moi, après 50 minutes de désespoir:

JTextPane.grabFocus(); 
JTextPane.setCaretPosition(20); 
Questions connexes