JTextArea Número de línea e Ir a línea específica

Iniciado por leogtz, 10 Octubre 2010, 18:02 PM

0 Miembros y 1 Visitante están viendo este tema.

leogtz

Hola, estoy haciendo un visor de documentos de texto(sí lo sé, es una estupidez, pero quiero practicar un poco de componentes en Java, aparte que tengo cientos de libros en .txt y me sería útil).

Bueno, lo que hago para volcar todo al JTextArea es leer el archivo con un Scanner y en cada línea hacer un append al JTextArea, así:
Código (java) [Seleccionar]

File file = fc.getSelectedFile();
                       filename = file.getAbsolutePath();
                       lblNameFile.setText(filename);
                       // Leer archivo:
                       File archivo = new File(filename);
                       Scanner sc = new Scanner(archivo);
                       sc.useDelimiter("\n");
                       String linea;
                       while (sc.hasNext())
                       {
                           linea = sc.next();
                           texto.append((linea.isEmpty() ? " " : ++lineNumber) + "\t" + linea + "\n");
                       }
                       lineNumber = 0;
                       sc.close();


Funciona bien, el problema es que el scroll se va hasta abajo(estamos hablando de unas 3000 líneas por archivo de texto), así que quisiera que aunque todo fuese volcado al JTextArea, el scroll quedará en la primera línea, ¿podrían decirme cómo?

Otra cosa, quisiera un método Ir a, ¿hay algo que me permita ir a cierta línea en el JTextArea?

Usé este método para obtener el número de línea(algo rústico, pero funciona):

Código (java) [Seleccionar]
while (sc.hasNext())
                       {
                           linea = sc.next();
                           texto.append((linea.isEmpty() ? " " : ++lineNumber) + "\t" + linea + "\n");
                       }


Les dejo todo el código para que lo prueben, de antemano gracias.

http://rapidshare.com/files/424244300/TextViewer.java

http://www.megaupload.com/?d=M5EZAF8X

EDITO:

He solucionado lo de poner el cursor en la primera línea así:

texto.setCaretPosition(0);

Ahora me queda otra duda, estoy teniendo problemas al abrir archivos con espacios con el Scanner, ¿alguien sabe como resolverlo?
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

Leyer

#1
Es raro no debería darte problemas ya que estas seteando el delimitador a \n mm de todas formas usas el nextLine().

El condicional ternario hace poco hay, si no haces linea.isEmpty() te contaría la linea en blanco.

Hice este método que permite ir a una especifica.

Código (java) [Seleccionar]
void ir(int line,JTextArea area){
       String []t = area.getText().split("\n");
int position=0;
for(int index=0;index<t.length;index++){
if(index == line-1)break;
if(t[index].length()!=0)
       position+=t[index].length();
}
area.setCaretPosition(position+line-1);
}


Un saludo.

leogtz

Gracias, el único problema es que me pone la línea que quiero al final del JTextArea, tengo que corregir eso.

También me queda corregir que reciba nombres de archivos con espacios.
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

Leyer

#3
No la coloca al final, la coloca al inicio

leogtz

#4
Qué raro, he especificado que vaya a la línea 50 en un archivo que tiene miles de líneas y deja la línea al final del JTextArea.

Código (java) [Seleccionar]

import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import java.awt.event.*;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.*;

public class TextViewer extends javax.swing.JFrame {
   
   void Ir(int line, JTextArea area)
   {
       String []t = area.getText().split("\n");
int position = 0;
for(int index = 0; index < t.length; index++)
       {
if(index == line - 1)
                   break;
if(t[index].length() != 0)
       position += t[index].length();
}
       area.setCaretPosition(position + line - 1);
   }
   
  int JTextLength(String fileName) throws FileNotFoundException
  {
      int longitud = 0;
      File archivo = new File(fileName);
      Scanner sc = new Scanner(archivo);
      sc.useDelimiter("\n");
      String linea;
     
      while (sc.hasNext())
      {
          linea = sc.next();
          longitud++;
      }
                       
      return longitud;
  }
   
   public TextViewer()
   {
       
       this.setLayout(new GridBagLayout());
       GridBagConstraints gbc = new GridBagConstraints();
       JScrollPane scroll = new JScrollPane(texto);
       gbc.fill = GridBagConstraints.BOTH;
       add(scroll, gbc);  
       
       JMenu file = new JMenu("File");
       JMenu help = new JMenu("Help");
       
       help.setMnemonic('H');
       file.setMnemonic('F');
       
       // Elemento del menú "Ayuda".
       JMenuItem aboutItem = new JMenuItem("Acerca de ...");
       aboutItem.setMnemonic('T');
       
       help.add(aboutItem);
       JMenuItem openItem = new JMenuItem("Abrir");
       openItem.setMnemonic('A');
       file.add(openItem);
       JMenuItem exitItem = new JMenuItem("Salir");
       exitItem.setMnemonic('S');
       file.add(exitItem);

       openItem.addActionListener(
new ActionListener()
       {
           public void actionPerformed(ActionEvent e)
           {
               texto.setEditable(false);
               texto.setText("");
               int lineNumber = 0;
String wd = System.getProperty("user.home");
JFileChooser fc = new JFileChooser(wd);
               Filtro filtro = new Filtro();
               filtro.addExtension("txt");
               filtro.setDescription("Archivos de texto plano : ");
               fc.setAcceptAllFileFilterUsed(false);
               fc.setFileFilter(filtro);
               
               fc.setDialogTitle("Seleccione el archivo de texto a abrir");
String filename = "";
int rc = fc.showDialog(null, "Seleccionar archivo");
if (rc == JFileChooser.APPROVE_OPTION)
{
                   try {
                       File file = fc.getSelectedFile();
                       filename = file.getAbsolutePath();
                       lblNameFile.setText(filename);
                       // Leer archivo:
                       File archivo = new File(filename);
                       Scanner sc = new Scanner(archivo);
                       sc.useDelimiter("\n");
                       String linea;
                       while (sc.hasNext())
                       {
                           linea = sc.next();
                           texto.append(++lineNumber + "\t" + linea + "\n");
                       }
                       //texto.setCaretPosition(0);
                       lineNumber = 0;
                       Ir(50, texto);
                       sc.close();
                   } catch (FileNotFoundException ex) {
                       Logger.getLogger(TextViewer.class.getName()).log(Level.SEVERE, null, ex);
                       JOptionPane.showMessageDialog(null, "Error abriendo la ***** : " + filename);
                   }
}
           }
}
       );


Saludos.

EDITO:

Al final queda así:



No quiero que los números de línea salgan en el texto, ¿alguna idea de qué componente usar para esto o cómo?
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

Leyer

#5
Eso es mas complicado de lo que parece  :xD , no sabria decirte la forma correcta de hacerlo...habria que chekear el src de jedit :P

leogtz

He encontrado esto, parece que funciona, voy a ver como lo adhiero al proyecto.


Código (java) [Seleccionar]
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.Document;

public class LineNr extends JPanel
{
  JTextPane pane;
  JScrollPane scrollPane;

  public LineNr ()
  {
    super ();
    setMinimumSize (new Dimension (30, 30));
    setPreferredSize (new Dimension (30, 30));
    setMinimumSize (new Dimension (30, 30));
    pane = new JTextPane () // we need to override paint so that thelinenumbers stay in sync
    {
      public void paint (Graphics g)
      {
super.paint (g);
LineNr.this.repaint ();
      }
    };
    scrollPane = new JScrollPane (pane);
  }

  public void paint (Graphics g)
  {
    super.paint (g);
    int start =
      pane.viewToModel (scrollPane.getViewport ().getViewPosition ());
    int end =
      pane.
      viewToModel (new
   Point (scrollPane.getViewport ().getViewPosition ().x +
  pane.getWidth (),
  scrollPane.getViewport ().getViewPosition ().y +
  pane.getHeight ()));
    Document doc = pane.getDocument ();
    int startline = doc.getDefaultRootElement ().getElementIndex (start);
    int endline = doc.getDefaultRootElement ().getElementIndex (end);
    int fontHeight = g.getFontMetrics (pane.getFont ()).getHeight (); // font
    for (int line = startline, y = 0; line <= endline;
line++, y += fontHeight)
      {
g.drawString (Integer.toString (line), 0, y);
      }

  }

  public static void main (String[]args)
  {
    JFrame frame = new JFrame ();
    frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
    frame.getContentPane ().setLayout (new BorderLayout ());
    final LineNr nr = new LineNr ();
    frame.getContentPane ().add (nr, BorderLayout.WEST);
    frame.getContentPane ().add (nr.scrollPane, BorderLayout.CENTER);
    frame.pack ();
    frame.setSize (new Dimension (400, 400));
//frame.show();
    frame.setVisible (true);
  }
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

Leyer

 :D :D excelente, así que era dibujando a mi también me servirá ese ejemplo ;)

leogtz

#8
Hola, LEYER, estoy teniendo muchos problemas para adaptar el código a mi proyecto, ¿podrías echarme una mano?

Te subo el proyecto entero por si deseas echarle un vistazo, yo mientras sigo intentando.

http://www.megaupload.com/?d=1W8QBWFV

EDITO:

Encontré esto, pero no lo logro adaptar a mi código :(
Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com

Leyer

#9
No puedo editar ese code en netbeans :-\ por que hay que modificar ciertas cosas de la GUI. ahora bien te dire lo que tienes que hacer.

Donde vas a colocar el area de texto, hay vas a hacer un panel sin ningún componente agregado.

Luego en el constructor harás lo siguiente.
Le quitas el main a  LineNr

 
Código (java) [Seleccionar]
public NewJFrame1() {
       setTitle("Test");
       initComponents();
       jPanel1.setLayout(new BorderLayout()); //seteas el layaut del panel creado

       LineNr s=new LineNr();
       jPanel1.add(s,BorderLayout.WEST); //contador
       jPanel1.add(s.scrollPane,BorderLayout.CENTER); //area de texto

       pack();
   }


Y ya con eso  bastaría.