Normalmente un JTable en Java viene con un aspecto previamente definido, desde el formato de los textos y números, el color de fondo de las celdas, la alineación del texto, etc. Sin embargo, existen ocasiones en que es necesario cambiar dicho formato, por ejemplo, cambiar el color de fondo de las celdas, filas, columnas, el tipo, color y estilo de las letras, la alineación, etc. Incluso en ocasiones dicho formato es condicional, es decir, solo aplica cuando alguno(s) de los datos cumplen ciertos requisitos.
En esta ocasión dedicaré este artículo a explicar paso a paso cómo cambiar el formato de las celdas en una tabla, para ello, vamos a necesitar de una clase que implemente la interface TableCellRenderer.
::La interface TableCellRenderer::
TableCellRenderer es una interface que provee del comportamiento a cada una de las celdas en un JTable, a través de ella, podemos definir los colores, formatos, alineaciones y demás cuestiones visuales de la tabla, al implementar dicha interfaz solamente es necesario definir el comportamiento del método getTableCellRendererComponent() y dentro de él definir lo que se desea.
El dicho método tiene la siguiente estructura:
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Donde:
table: Es la tabla contenedora de la celda actual.
Object: El contenido de la celda.
isSelected: Indica si dicha celda está seleccionada o no.
hasFocus: Indica si dicha celda tiene o no el foco.
row: La fila en la que se encuentra ubicada la celda.
column: La columna en la que se encuentra ubicada la celda.
Ya que conocemos el método que se va a utilizar pasemos con la definición de la clase.
::Definición de la clase::
La clase que utilizaremos debe de heredar de cualquier tipo de objeto derivado de la clase Component, desde un campo de texto (JTextField) hasta incluso un panel (JPanel) que a su vez podrá contener cualquier otro componente. En este caso utilizaré el componente JFormattedTextField ya que en mi caso necesito darle cierto formato a los datos que manejarán cantidades monetarias.
La definición inicial de la clase queda de la siguiente manera:
public class FormatoTabla extends JFormattedTextField implements TableCellRenderer{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,boolean hasFocus, int row, int column) {
}
}
Ahora bien, lo siguiente que debemos hacer es definir un objeto del tipo de la clase que vamos a estar manejando, en este caso un JFormattedTextField para irle dando el formato que deseamos. En este ejemplo lo definí dentro del método aunque puedes hacerlo como te sea más útil en tu aplicación…
JFormattedTextField campoTexto = new JFormattedTextField();
…posteriormente le establecí un borde vacío para que siguiera adaptándose al estilo de la tabla como normalmente la vemos…
campoTexto.setBorder(BorderFactory.createEmptyBorder());
…una vez hecho esto, vamos a aplicar el formato a la celda de acuerdo al tipo de dato que esta contenga, en mi caso la celda puede contener uno de 3 tipos: String, Integer o BigDecimal, que son los cuales voy a estar validando de la siguiente manera:
- Si el objeto es de tipo String únicamente lo escribo en el campo de texto sin cambiar su formato:
if (value instanceof String){
campoTexto.setText((String)value);
}
- Si el objeto es de tipo Integer escribo su valor y lo alineo al centro:
if(value instanceof Integer){
campoTexto.setText(""+(Integer)value);
campoTexto.setHorizontalAlignment(SwingConstants.CENTER);
}
- Si el objeto es tipo BigDecimal además de escribir su valor le aplico un formato para que me separa por comas cada 3 cifras y establezco su alineación de derecha a izquierda…
campoTexto.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#,##0.00"))));
campoTexto.setHorizontalAlignment(SwingConstants.TRAILING);
campoTexto.setValue(valor);
…pero si además su valor es negativo, le quito el signo menos (-) y le establezco su color de fondo a rojo…
if(valor.compareTo(new BigDecimal(0))==-1) {
campoTexto.setText(etiqueta.getText().replace("-", ""));
campoTexto.setBackground(new Color(0xFE899B));
campoTexto.setOpaque(true);
}
…al hacer lo anterior solo la celda que contiene el valor negativo se dibujará de color rojo, sin embargo, en mi caso deseo que todas las celdas de dicha fila sean rojas así que agregué el siguiente código:
if(((BigDecimal)table.getValueAt(row, table.getColumnCount()-1)).compareTo(new BigDecimal(0))==-1){
campoTexto.setBackground(0xFE899B);
campoTexto.setOpaque(true);
}
Lo que hago en las líneas anteriores es verificar si en la última celda del lado derecho de la fila en la que se encuentra la celda actual se localiza un valor negativo, en caso de ser así cambio el color de fondo de la celda actual a rojo claro.
Para terminar vamos a definir el comportamiento de las celdas al estar seleccionadas, en este caso, vamos a cambiar su color de fondo por un tono gris claro…
if(isSelected){
etiqueta.setBackground(Color.lightGray);
}
Cuando desees utilizar el formato que hemos definido anteriormente en alguna de las tablas de tu aplicación basta con realizar lo siguiente:
FormatoTabla formato = new FormatoTabla();
tabla.setDefaultRenderer(BigDecimal.class, formato);
tabla.setDefaultRenderer(String.class, formato);
tabla.setDefaultRenderer(Integer.class, formato);
Con lo anterior estoy indicando que para la tabla ‘tabla’ se utilice el formato definido en la clase FormatoTabla para cada celda donde su valor sea de tipo BigDecimal, String e Integer.
Tras realizar todo lo anterior tendrás una tabla con un formato parecido a la siguiente:
Si lo deseas puedes descargar el código fuente de la clase FormatoTabla desde el siguiente vínculo:
La contraseña para descomprimirlo es: http://monillo007.blogspot.com
Alguna duda o algo qué decir? Deja tu comentario. Saludox.
Hola buen dia, excelente tu explicacion bastante buena diria yo, solo quu quiero descargar el codigo fuente ´pero el link no funciona.
ResponderBorrarGracias . . .
Hola muy bueno tut tuto ,yo tambien quiero descargar el codigo . . . .
ResponderBorrarHola muy bien explicado pero no me funciona al implementarlo en mi aplicación, me gustaría ver el codigo para ver en que estoy fallando Muchas Gracias.
ResponderBorrarPues a mi también me pareció muy útil pero cuando lo trate de probar en mi aplicación no funciono. El link de descarga no funciona :(
ResponderBorrarHola
ResponderBorrarEn primer lugar gracias por tu aporte, me gustaría poder descargar el codigo fuente.
El link que dejaste no funciona, podrías enviarmelo. Mi correo es marll_star@yahoo.com.mx
Gracias por tu atencion.
El link de descarga no funciona ... te agradeceria me lo pudieras enviar a mi correo... ya que me seria de mucha ayuda.
ResponderBorrarDe antemano muchas gracias y felicidades por tu Blog tan bueno.
mi correo.
joel.sys@hotmail.com
Hola. Me parece interesante tu aporte... y me gustaria bajar el codigo fuente lo cual me será de mucha ayuda, pero el link no funciona. Te agradezco me lo envias a mi correo:
ResponderBorrarwserpa@gmail.com.
Te antemano muchas gracias
muy buenos post gracias Monillo007
ResponderBorrarGracias por el post logre hacerlo sin necesidad de copiar y pegar, me ayudaste. Saludos
ResponderBorrarExcelente aporte, muchas gracias me sirvió de mucho
ResponderBorrarAtte, PlayGame
Hay un error o es etiqueta o es campoTexto, esto pasa por copiar y pegar de otras páginas ...
ResponderBorrarif(isSelected){
etiqueta.setBackground(Color.lightGray);
}
Te falta el return campoTexto;
...Pobre gente que quiere hacer andar este código ....
import java.awt.Color;
ResponderBorrarimport java.awt.Component;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
public class TableRendererFTextField implements TableCellRenderer {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JFormattedTextField txtFormated = new JFormattedTextField();
txtFormated.setBorder(BorderFactory.createEmptyBorder());
fillColor(table,txtFormated,isSelected);
txtFormated.setText(""+ value);
txtFormated.setHorizontalAlignment(SwingConstants.CENTER);
if(((Float)table.getValueAt(row, table.getColumnCount()-2)).compareTo(new Float(0))==-1) {
txtFormated.setBackground(new Color(0xFE899B));
txtFormated.setOpaque(true);
if(isSelected){
txtFormated.setBackground(Color.lightGray);
}
}
return (txtFormated);
}
public void fillColor(JTable t, JFormattedTextField JFTextField, boolean isSelected) {
if (isSelected) {
JFTextField.setBackground(t.getSelectionBackground());
JFTextField.setForeground(t.getSelectionForeground());
} else {
JFTextField.setBackground(t.getBackground());
JFTextField.setForeground(t.getForeground());
}
}
}
Donde declaras la variable "valor"
ResponderBorrarQué tal Mike,
ResponderBorrar'valor' es valor que vas a establecer en la fila, en este ejemplo sería tipo texto ;)
Saludos.
Alguien me puede enviar el codigo completo por email.
ResponderBorrarEl enlace no funciona.
gracias
jesuseti@hotmail.com
El linkde la descarga del código ya no sirve! Podrías resubirlo nuevamente?? Gracias!! :D
ResponderBorrarEl link no esta disponible.....hermano sera que lo puede subir nuevamente?
ResponderBorrarPodrías activar el linck de descarga otra ves?
ResponderBorrarvuelve a subir tu codigo por q no sirve
ResponderBorrarhola que tal alguien me podria enviar el codigo a mi correo por favor
ResponderBorrarchias@live.com.mx
Hola amigo muy buena tu explicación pero podrías subir el código nuevamente o enviármelo por correo sheikav22@hotmail.com te lo agradecería ya que llevo mucho tiempo buscando como hacerto en mis proyectos.
ResponderBorrarCual es la contrasenia? gracias de antemano
ResponderBorrarCUal es la contraseña alguien me la podria pasar mi correo es cobra_1884@hotmail.com
ResponderBorrartiene contraseña al descomprimir el carchovo...alguien me puede proorcionar la contraseña...gracias
ResponderBorrarQué tal,
ResponderBorrarLa contraseña está al final del post, es:
http://monillo007.blogspot.com
Saludos.
Muy buena publicación pero....
ResponderBorrarPero tengo unos problemas.
ResponderBorrar1.- Que veo que tus ejemplo trae los datos fijos.
2.- Y yo necesito llenar de una tabla de EBCDIC, (Este tema ya lo soluciones) ya convierto los datos a String
3.- No hayo la manera de mandar ejecutar tu proceso para que me realice el cambio en la tabla.
4.- Puedo crear una clase exclusiva para mandar los datos por paremetro y me regrese el valor del llenado de la tabla?
5.- Esto es por que son varias tablas con las cuales ocupare la salida formateada de los importes ejemplo recibo 1234567890 y requiero que salga $ 12,345,678.90
Espero me puedas ayuda ru orientar en que parte de mi ciclo while coloco tu proceso para que sea ejecutado obvio quitando los valores fijos.
Gracias de antemano
Saludos.
Gracias la explicación esta detallada y me sirvió de mucho
ResponderBorrar