2012-05-21 10 views
13

Ich habe hier eine einfache Java-Frage. Ich möchte den automatischen Textscrollvorgang bis zum Anfang der letzten Zeile eines mit JTextArea erstellten Textbereichs durchführen. Die Textmenge pro Zeile des Textbereichs ist länger als die Breite des Textbereichs.Automatischer Textscroll für Textbereich (JTextArea) mit Caret-Position an den Anfang der letzten Zeile gesetzt

Hier ist das Code-Snippet, das ich verwendet habe, um das einzurichten.

JTextArea textArea = new JTextArea(); 
DefaultCaret caret = (DefaultCaret)textArea.getCaret(); 
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); 

Das Problem ist jetzt, mit dem obigen Code, ist das Standardverhalten, dass die caret Auto bis zum Ende des Dokuments positioniert ist, als Ergebnis erhält der Anfangsteil des gesamten Textbereiches Umfang aus . Ich würde es vorziehen, dass der automatische Bildlauf am Anfang der letzten Zeile im Dokument stattfindet.

Um deutlich zu machen, hier sind zwei Screenshots,

Was ich will, ist die erste, aber ist das, was passiert, die zweite.

What I want is this What I get is this

Antwort

13

einfach den Cursor an die richtigen Stelle bewegen Sie mit getLineCount und getLineStartOffset nach dem Text des Textbereiches zu aktualisieren.

Hier ist ein funktionierendes Beispiel Ihr gewünschtes Verhalten darstellt:

import java.util.List; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextArea; 
import javax.swing.SwingUtilities; 
import javax.swing.SwingWorker; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.DefaultCaret; 

public class Test { 

    private JFrame frame; 
    private JTextArea ta; 

    protected void initUI() { 
     frame = new JFrame(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     ta = new JTextArea(); 
     DefaultCaret caret = (DefaultCaret) ta.getCaret(); 
     caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); 
     frame.add(new JScrollPane(ta)); 
     frame.setSize(400, 200); 
     frame.setVisible(true); 
     new UpdateText().execute(); 
    } 

    class UpdateText extends SwingWorker<String, String> { 

     @Override 
     public String doInBackground() { 
      for (int i = 0; i < 1000; i++) { 
       publish("Hello-" + i); 
       try { 
        Thread.sleep(500); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
      return null; 
     } 

     @Override 
     public void process(List<String> chunks) { 
      for (String s : chunks) { 
       if (ta.getDocument().getLength() > 0) { 
        ta.append("\n"); 
       } 
       ta.append(s); 
      } 
      try { 
       ta.setCaretPosition(ta.getLineStartOffset(ta.getLineCount() - 1)); 
      } catch (BadLocationException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 

     @Override 
     public void done() { 

     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new Test().initUI(); 
      } 
     }); 
    } 

} 
+0

Coole Lösung! Aber ich habe eine Frage hier. Gibt es eine Möglichkeit, die ta.setCaretPosition (ta.getLineStartOffset (ta.getLineCount() - 1)); nur einmal statt es jedes Mal zu aktualisieren, damit es für die gesamte Anwendung gültig bleibt? –

+0

Darüber hinaus verwenden Sie DefaultCaret caret = (DefaultCaret) ta.getCaret(); caret.setUpdatePolicy (DefaultCaret.ALWAYS_UPDATE); Ihr Code würde auch ohne diese Anweisungen funktionieren? Was ist Ihrer Meinung nach in dieser Hinsicht? –

+0

@JtheRocker nicht, dass ich weiß. Die Caret-Position bewegt sich weiter, während der Text aktualisiert wird. Aus diesem Grund muss der Standort jedes Mal neu berechnet werden. Sie könnten wahrscheinlich JTextArea erweitern und setText überschreiben, indem Sie zuerst super.setText aufrufen und dann das Caret positionieren. Was Ihre zweite Frage betrifft, ist dies eine Frage des gewünschten Verhaltens und der Ergonomie. In Ihrer Frage haben Sie danach gefragt. Wenn Sie jetzt nach der unteren linken Ecke des Bildlauffelds scrollen, suchen Sie nach etwas anderem. Wenn ja, dann erwäge, eine weitere Frage zu SO zu stellen. –