2012-05-21 30 views
13

Mam proste pytanie Java tutaj. Chcę automatycznie przewinąć tekst do początku ostatniego wiersza obszaru tekstowego utworzonego za pomocą JTextArea. Ilość tekstu w wierszu obszaru tekstowego jest dłuższa niż szerokość pola tekstowego.Automatyczne przewijanie tekstu dla obszaru tekstowego (JTextArea) z pozycją caret ustawioną na początku ostatniej linii

Oto fragment kodu Kiedyś to ustawiłem.

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

Problem jest teraz z powyższym kodem, domyślnym zachowaniem jest to, że karetka jest automatycznie umieszczony na końcu dokumentu, w rezultacie, na początku część całego obszaru tekstu wychodzi z zakresu . Wolałbym, aby automatyczne przewijanie stało się początkiem ostatniej linii w dokumencie.

Żeby było jasne, tu są dwa zrzuty ekranu,

Co chcę jest pierwszym, ale to, co się dzieje jest drugi.

What I want is this What I get is this

Odpowiedz

13

Wystarczy przesunąć karetkę do właściwej lokalizacji za pomocą getLineCount i getLineStartOffset po aktualizacji tekstu textarea.

Oto przykład ilustrujący pracę żądane zachowanie:

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

super rozwiązanie! Ale mam tutaj pytanie. Czy istnieje sposób, w jaki mogę ustawić ta.setCaretPosition (ta.getLineStartOffset (ta.getLineCount() - 1)); tylko jeden raz, zamiast aktualizować go za każdym razem, aby zachować ważność dla całej aplikacji? –

+0

Ponadto, mimo że używasz DefaultCaret caret = (DefaultCaret) ta.getCaret(); caret.setUpdatePolicy (DefaultCaret.ALWAYS_UPDATE); Twój kod działałby również bez tych instrukcji? Jaki jest twój punkt widzenia w tym zakresie? –

+0

@JtheRocker nie, że wiem. Pozycja chroniona porusza się wraz z aktualizacją tekstu. Dlatego oznacza to, że jego lokalizacja musi zostać ponownie obliczona za każdym razem. Prawdopodobnie możesz rozszerzyć JTextArea i przesłonić setText, najpierw wywołując super.setText, a następnie ustaw daszek. Jeśli chodzi o twoje drugie pytanie, jest to kwestia pożądanych zachowań i ergonomii. W twoim pytaniu jest to, o co prosiłeś. Teraz, jeśli szukasz w rzeczywistości przewijania do lewego dolnego rogu przewijania, to szukasz czegoś innego. Jeśli tak, to rozważ umieszczenie kolejnego pytania na SO. –