2012-05-21 11 views
13

Tengo una pregunta de Java simple aquí. Quiero desplazar automáticamente el texto al principio de la última línea de un área de texto creada con JTextArea. La cantidad de texto por línea del área de texto es bastante más larga que el ancho del área de texto.Desplazamiento de texto automático para el área de texto (JTextArea) con la posición de acotación establecida al principio de la última línea

Aquí está el fragmento de código que utilicé para configurarlo.

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

El problema ahora es, con el código anterior, el comportamiento predeterminado es que el cursor se auto posicionado para el final del documento, como resultado, la parte inicial de toda el área de texto se sale de alcance . Prefiero que el desplazamiento automático pase al principio de la última línea del documento.

Para que quede claro, aquí hay dos capturas de pantalla,

Lo que quiero es el primero, pero lo que sucede es que el segundo.

What I want is this What I get is this

Respuesta

13

Basta con mover el cursor a la ubicación correcta utilizando getLineCount y getLineStartOffset después de actualizar el texto del área de texto.

Aquí es un ejemplo de trabajo que ilustra el comportamiento deseado:

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

enfría la solución! Pero tengo una pregunta aquí. ¿Hay alguna manera de que pueda establecer ta.setCaretPosition (ta.getLineStartOffset (ta.getLineCount() - 1)); solo una vez en lugar de actualizarlo cada vez, para que siga siendo válido para toda la aplicación? –

+0

Además, aunque está utilizando DefaultCaret caret = (DefaultCaret) ta.getCaret(); caret.setUpdatePolicy (DefaultCaret.ALWAYS_UPDATE); ¿Su código funcionaría sin estas declaraciones también? ¿Cuál es su opinión al respecto? –

+0

@JtheRocker no es que yo sepa. La posición de intercalación se sigue moviendo a medida que se actualiza el texto. Por lo tanto, esto significa que su ubicación debe ser recalculada cada vez. Probablemente puedas extender JTextArea y anular setText, primero llamando a super.setText y luego colocando el símbolo de intercalación. En cuanto a su segunda pregunta, esta es una cuestión de comportamiento deseado y ergonomía. En tu pregunta, eso es lo que pediste. Ahora, si estás mirando en realidad desplazándote hacia la esquina inferior izquierda del panel de desplazamiento, entonces estás buscando algo más. Si es así, considere publicar otra pregunta en SO. –

Cuestiones relacionadas