Question

J'ai quelques milliers de lignes de code quelque part et je l'ai remarqué que mon JTextPane vacille quand je le mettre à jour trop .. je l'ai écrit une version simplifiée ici:

import java.awt.*;
import javax.swing.*;

public class Test
{
    static JFrame f;
    static JTextPane a;
    static final String NL = "\n";

    public static void main(String... args)
    {
        EventQueue.invokeLater(new Runnable(){
        public void run()
        {
        f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.setSize(400, 300);
        f.setLocationRelativeTo(null);

        a = new JTextPane();
        f.add(new JScrollPane(a));

        new Thread(new Runnable(){
            public void run()
            {
                int i = 0;
                StringBuffer b = new StringBuffer();
                while(true)
                {
                    b.append(++i+NL);
                    a.setText(b.toString());
                    a.setCaretPosition(b.length());
                    try{Thread.sleep(10);}catch(Exception e){}
                }
            }
        }).start();
        }
        });

    }
}

Ceci est pour un composant graphique de style terminal (cmd) -

Je pense que je l'ai fait toutes les optimisations que je pouvais ici, y compris avoir comme une variable \n finale, donc il ne sera pas construit des centaines de fois. Pourtant, le scintillement est notable et inacceptable. Après quelques minutes, le composant se fige complètement. Je dois mettre à jour le composant très rapidement, et la vitre doit être défilée au fond quand mis à jour.

J'ai pensé à faire ma propre version de JTextPane à partir de zéro, mais je voudrais voir si les gars vous avez une solution plus facile.

Était-ce utile?

La solution

Une partie de votre erreur est que vous accédez à un composant Swing à l'extérieur du thread d'événement! Oui, setText ( ) est thread-safe, mais les méthodes Swing ne sont pas thread-safe à moins qu'ils ne soient explicitement déclarés comme tels. Ainsi, setCaretPosition () est pas thread-safe et doit être accessible à partir du thread d'événement. Ceci est presque certainement la raison pour laquelle votre application se fige par la suite.

NOTE: sa méthode hérite JTextPane de setText() et sa méthode JEditorPane de setCaretPosition JTextComponent, ce qui explique les liens dans le paragraphe précédent ne va pas à la balise setCaretPosition() JavaDoc.

Pour être en sécurité-fil, vous avez vraiment besoin d'au moins appeler à l'intérieur du <=> fil des événements, que vous pouvez faire avec le code comme ceci:

SwingUtilities.invokeAndWait(new Runnable() {
  public void run() {
    a.setText(b.toString());
    a.setCaretPosition(b.length());
  }
}

Et puisque vous devez appeler à partir du <=> thread d'événement, vous pourriez aussi bien appeler aussi de la même <=> lieu.

Il est possible que vous ne pouvez pas besoin de régler manuellement la position de caret. Consultez la section "Caret" Les changements dans la JavaDoc pour JTextComponent .

Enfin, vous pouvez consulter une série de deux articles:

Autres conseils

Je ne sais pas si cela va fonctionner, mais vous pouvez essayer d'utiliser la méthode de insertString() l'instance de Document le volet texte. Je voudrais essayer d'avoir un seul espace à la fin du document et en gardant le curseur positionné après que l'espace; mais lorsque vous insérez une chaîne, insérez avant l'espace. De cette façon, la position de caret restera à la fin du document automatiquement.

Je pense que le volet texte pourrait obtenir redessinée deux fois, une fois que lorsque vous appelez et une fois quand setText() vous appelez setCaretPosition(), et qui pourrait contribuerez à la vacillante. Je ne sais pas, mais (ça fait un moment que je travaillais avec Swing).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top