J'ai intégré un JTextArea sur un JScrollPane et j'utilise ce JTextArea pour la sortie.
Je veux que chaque fois que la sortie dépasse la taille du JTextArea, le JTextArea défile automatiquement pour que l'utilisateur n'ait pas à faire défiler manuellement vers le bas pour voir la sortie récente.
Comment puis je faire ça?
J'ai déjà défini la propriété autoscroll de JTextArea et JScrollPane sur true.
Lorsque vous utilisez JDK1.4.2 (ou une version antérieure), la suggestion la plus courante que vous trouverez dans les forums est d'utiliser un code similaire à celui-ci:
textArea.append(...);
textArea.setCaretPosition(textArea.getDocument().getLength());
Cependant, je viens de remarquer que dans JDK5, ce problème avait été résolu par une modification de l'API. Vous pouvez maintenant contrôler ce comportement en définissant une propriété sur le DefaultCaret de la zone de texte. En utilisant cette approche, le code serait:
JTextArea textArea = new JTextArea();
DefaultCaret caret = (DefaultCaret)textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
Vous trouverez une description plus détaillée de ce sujet ici: Défilement de la zone de texte
Lorsque vous cliquez n'importe où sur JTextArea, le défilement automatique peut être arrêté. Comme la position du curseur a changé une fois, le point de vue a également changé. Pendant ce temps, vous devez définir la position du curseur lorsque vous ajoutez ou ajoutez du texte. En chemin, j'ai créé une méthode comprenant la position du curseur, puis je l’utilise quand il faut ajouter quelque chose.
JScrollBar vbar = scrollPane.getVerticalScrollBar();
for (int i = 0; i < 20; i++) {
myJTxt.append("This is text " + i + "\n");
vbar.setValue(vbar.getMaximum());
vbar.Paint(vbar.getGraphics());
myJTxt.scrollRectToVisible(myJTxt.getVisibleRect());
myJTxt.Paint(myJTxt.getGraphics());
try {
Thread.sleep(250);
} catch (InterruptedException ex) {
Logger.getLogger(ScrollTextView.class.getName()).log(Level.SEVERE, null, ex);
}
}
JTextArea jTextArea = new JTextArea();
DefaultCaret caret = (DefaultCaret)jTextArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.OUT_BOTTOM);
J'ai essayé la plupart des suggestions, mais j'ai rencontré des problèmes lorsque le contenu de JTextArea est volumineux (plusieurs Mo). Enfin, les résultats suivants ont montré les meilleures performances:
myTextArea.append( someText );
myTextArea.getCaret().setDot( Integer.MAX_VALUE );
Bien entendu, toute sélection effectuée par l'utilisateur est perdue. Par conséquent, il est uniquement utilisable pour une utilisation "affichage uniquement" de la zone de texte.
Néanmoins, dans mon installation, si le contenu de JTextArea dépasse environ 9 Mo, il devient un peu inutilisable (interface graphique très lente à presque figée).
Un phénomène similaire se produit lorsque le texte contient des caractères représentés par deux caractères (deux unités de 16 bits) dans le codage UTF-16 (appelées paires de substitution, comme ceci: ????). J'ai une solution pour le filtrage, mais peut-être un sujet différent.