En java tenemos varios componentes visuales que nos permiten escribir texto o pedírselo al usuario. Cada uno de estos componentes es adecuado para una cosa. Vamos a ver cuales son y veremos un ejemplo de los dos más complicados y completos.
Los componentes de texto son:
Vamos a ver aquí un ejemplo de los dos últimos. Del JEditorPane y del JTextPane.
Como ya hemos comentado, el JEditorPane admite texto con cierto formato. Por defecto conoce el texto plano, el HTML y el RTF, aunque debemos decirle a priori qué es lo que va a usar.
JEditorPane editor = new JEditorPane();
...
// Marcamos el editor para que use HTML
editor.setContentType("text/html");
...
// o para que use RTF
editor.setContentType("text/rtf");
...
// o para texto normalito
editor.setContentType("text/plain");
El tipo de texto normalito "text/plain" es el de defecto, así que si no indicamos nada, es el que se usará.
Si queremos construir otros formatos, debemos heredar de javax.swing.text.EditorKit y construirnos una clase definiendo todos los métodos abstractos. Sin embargo eso es mucho para este tutorial, así que simplemente saber que existe esa posibilidad.
Para los formatos que java entiende, java nos proporciona clases que heredan de EditorKit y saben tratar los tipos de texto mencionados, pero el JEditorPane las maneja internamente y no nos enteraremos de su existencia, pero que sepas que son DefaultEditorKit, HTMLEditorKit y RTFEditorKit.
Vamos con el caso de HTML. Una vez configurado nuestro editor, simplemente tenemos que meterle un texto HTML con setText(), así
// Marcamos el editor para
que use HTML
editor.setContentType("text/html");
// Insertamos un texto
editor.setText(
"<b>hola</b><br>" + "<i>adios</i><br>"
+
"<font face=\"arial\">fuente arial</font><br>"
+
"<font face=\"courier\">fuente courier</font><br>"
+
"<font size=\"24\">fuente grande</font><br>"
+
"<font color=\"red\">color rojo</font><br>"
+
"<img src=\"file:d:/viejo.gif\"></img>");
Como ves, no me he preocupado de poner los tags <html>, <head> ni <body>, aunque se debería. De todas formas, funciona bien.
En ese texto hay negritas, cambios de fuente de letra, tamaño, color e incluso una imagen. Fijate que he tenido que "escapar" las comillas, poniendo un \ delante, para distinguirlas de las comillas de principio y fin del texto java. La imagen la he puesto con path absoluto y de fichero, aunque se puede poner también una imagen remota con http://dominio.com/path/unaImagen.gif o lo que se quiera. De hecho, el método setPage() de esta clase admite una URL y es capaz de leer una página completa a través de internet.
JEditorPane no tiene métodos para ir añadiendo más texto, así que a través de setText() debemos dar todo el texto del golpe. Si queremos hacer modificaciones -añadir más texto, borrar, modificar-, debemos pedir el Document con el método getDocument() y trabajar con él, aunque no es trivial.
Si para la imagen quieres usar path relativos, debes ser más cuidadoso, puesto que ... ¿relativos a qué directorio?. Para usar path relativos, tienes que indicar el tab <base> en el <head> del HTML. Sería esto más o menos
// Insertamos un texto
editor.setText(
"<head><base href=\"file:d:/\"></head>"+
"<b>hola</b><br>" + "<i>adios</i><br>"
+
"<font face=\"arial\">fuente arial</font><br>"
+
"<font face=\"courier\">fuente courier</font><br>"
+
"<font size=\"24\">fuente grande</font><br>"
+
"<font color=\"red\">color rojo</font><br>"
+
"<img src=\"viejo.gif\"></img>");
La ventana al ejecutar esto sería
y el código completo es EjemploJEditorPaneHtml.java.
Para RTF es exactamente igual, pero cambian los datos. Esta sería la forma
// Se le dice al editor que va a usar RTF
editor.setContentType("text/rtf");
// Un texto en RTF
editor.setText(
"{\\rtf1" +
"{\\colortbl ;\\red255\\green0\\blue0;}" +
"Esto\\par " +
"es una \\b prueba\\b0 de \\i cursiva\\i0\\par " +
"y \\cf1 todo\\cf0 \\par" + "}");
Bueno, el texto en formato RTF es un poco raro para los que, como yo, no estamos acostumbrados a él. Usa muchas \ que hemos tenido que "escapar" poniendo \\ para que el compilador de java no las interprete -mejor dicho, interprete \\ como \-.
Simplemente comenzamos el texto con un {\rtf1, definimos una tabla de colores con un solo color RGB rojo, ponemos un par de párrafos con negrita \b y cursiva \i y luego un todo de color rojo con \cf1 y \cf0. No voy a explicar aquí más detalles de RTF, pero si tienes interés no te costará encontrar algo por internet.
El caso es que mostrando este editor, tenemos la siguiente foto
y el código java para mostrar esta ventana es EjemploJEditorPaneRtf.java.
JTextPane es otro editor que admite colores, fuentes, tamaños, etc. Admite incluso que el pongamos directamente iconos pasándole una clase Icon de java o que le añadamos Component de java, como JButton, JLabel, etc.
Para añadir texto, debemos ir añadiéndolo indicando en cada caso que "atributos" queremos para ese texto. Si lo queremos en negrita, con tal fuente de letra, tamaño, tal color, etc.
Sin embargo, estos componentes JEditorPane y JTextPane no tienen métodos para ir añadiendo poco a poco el texto. Simplemente tienen un método setText() al que se pasa todo el texto de golpe. Para poder trabajar con el JTextPane, debemos pedirle el Document asociado con getDocument() y trabajar con él, que sí tiene métodos para ir añadiendo texto poco a poco.
Por ejemplo, para añadir un trozo de texto en negrita, haríamos esto
// Se instancia el JTextPane
JTextPane editor = new JTextPane();
// Atributos para la frase,
en negrita
SimpleAttributeSet attrs = new SimpleAttributeSet();
StyleConstants.setBold(attrs, true);
// Se inserta
editor.getStyledDocument().insertString(
editor.getStyledDocument().getLength(), "Negrita", attrs);
La parte de instanciar el editor no debería presentar ningún problema.
Luego hemos instanciado una clase SimpleAttributeSet. Esta clase es la que guardará los atributos para un determinado texto: si es negrita, cursiva, fuente, etc. Para modificar el valor de estos atributos, nos ayuda la clase StyleConstants. Esta clase tiene muchos métodos para cambiar valores a una clase SimpleAttributeSet. En este caso concreto hemos usado setBold() para ponerlo en negrita.
StyleConstants.setBold(attrs, true);
Luego, simplemente, hemos insertado el texto. Pero esto requiere una pequeña explicación.
Primero obtenemos el StyledDocument, que es lo que el JTextPane tiene dentro y representa al texto que estamos viendo.
editor.getStyledDocument()
El StyledDocument tiene un método insert() que admite tres parámetros:
Como queremos insertar al final, la posición es justo la longitud del texto. Eso se obtiene con el método getLength() así
editor.getStyledDocument().getLength()
Los otros dos parámetros son simplemente el texto "Negrita" y los atributos que fijamos antes.
También podemos insertar un icono. El método para ello es insertIcon(). Este método reemplaza lo que hay seleccioado en el JTextPane por el icono. Si sólo queremos insertarlo al final, debemos cambiar la selección del texto al final, sin seleccionar nada. Eso se hace con el método setCaretPosition().
El trozo de código para insertar un icono al final sería
// Ponemos el cursor de
seleccion al final del texto
editor.setCaretPosition(editor.getStyledDocument().getLength());
// Un icono
ImageIcon icono = new ImageIcon("d:/viejo.gif");
editor.insertIcon(icono);
Obtenemos la longitud del texto de la misma forma que antes. Usamos esa longitud para llevar allí la selección con el método setCaretPosition().
Luego, simplemente cargar el icono y añadirlo.
También podemos añadir un Component cualquiera. Por ejemplo, un JButton. El método es insertComponent() y, al igual que en el caso anterior, reemplaza el texto que haya seleccionado por el Component. Al igual que antes, con setCaretPosition() nos vamos al final del texto e insertamos el JButton.
// Ponemos el cursor al final del texto
editor.setCaretPosition(editor.getStyledDocument().getLength());
// insertamos un JButton
JButton boton = new JButton("Pulsame");
editor.insertComponent(boton);
Con todo esto y alguna cosa más, obtenemos el editor de la figura
y el código para obtener eso es EjemploJTextPane.java.