Mauricio Murillo_ Un Poco de Swing Usando JTable, DefaultComboBoxModel, AbstractTableModel
Transcript of Mauricio Murillo_ Un Poco de Swing Usando JTable, DefaultComboBoxModel, AbstractTableModel
Datos personales
Ver todo mi perfil
Sí consideras que la información
publicada en mi blog te fue de utilidad y
quieres realizar alguna contribución
económica para continuar mejorando el
contenido del sitio, haz clic en
DONATE!!!
Seguir 197 seguidores
Mis Valores
Profesionales
Agile Manifesto
Software Craftsmanship Manifesto
Certificaciones
Archivo
► 2013 (3)
► 2012 (30)
▼ 2011 (19)
► noviembre (2)
► octubre (2)
► julio (2)
► junio (4)
► mayo (1)
▼ abril (1)
Un poco de Swing usando JTable,
DefaultComboBoxMod...
► marzo (2)
► febrero (3)
Publicado por ingmmurillo 07/04/2011
Un poco de Swing usando JTable, DefaultComboBoxModel,
AbstractTableModel
Mauricio MurilloBienvenidos!!! En mi blog comparto mis experiencias y conocimientos relacionados con las tecnologías de integración de sistemas, lenguajes de
programación, bases de datos e Inteligencia de Negocios (BI). Technology is there, your choice is use it!!!
Posts RSS Comments RSS
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
1 de 9 05/04/2013 16:53
► enero (2)
► 2010 (32)
Anuncios
Entradas populares
En ésta publicación explico como usar TableModels y ComboBoxModels a través de la creación de un aplicación
creada en Swing que lee datos de una base de datos MySQL.
Requisitos
1. Java Development Kit (JDK) v1.6
2. MySQL Server 5 o superior
3. IDE de desarrollo, con el que se prefiera trabajar (Netbeans, Eclipse, IntelliJ)
4. MySQL GUI Tools (Descarga para Windows)
5. Conector JDBC para MySQL (Link de Descarga)
Modelo Simple de Datos Relacional
Vamos a partir del siguiente modelo de datos relacional que está conformado por 2 tablas. Una tabla empleado y su
relación con una tabla departamento .
En la figura se muestra que un empleado pertenecerá a un departamento.
Creación de la base de datos
Usando la herramienta MySQL Administrator nos conectamos al servidor de base de datos MySQL que se usará. En mi
caso MySQL está instalado en la misma máquina (localhost )
Una vez que estemos dentro de la aplicación, vamos a Tools > MySQL Query Browser para ejecutar las
siguientes sentencias SQL:
Luego procedemos a crear la estructura de datos física definida en el modelo, a través de las siguientes sentencias
SQL:
Por último insertamos los siguiente datos por defecto en las tablas empleado y departamento .
Creación del proyecto
En el IDE de su preferencia creamos un nuevo proyecto Java, con el nombre que deseen en mi caso
EjemploSwingTables y creamos los siguientes paquetes de Java:
En el paquete com.blogspot.ingmmurillo.domain crearemos los POJOs para representar las tablas de la base
01.02.03.04.05.06.07.08.09.10.11.12.13.14.
#Usar la base de datos mysqlUSE mysql; #Crear la base de datos TEST para realizar el ejemp loCREATE DATABASE test DEFAULT CHARACTER SET utf8; #Usar la base de datos testUSE test; #Crear un usuario para conectarse a la base de dato s TESTCREATE USER 'usuario' @'%' IDENTIFIED BY 'prueba' ; #Dar los permisos CRUD al usuarioGRANT SELECT, INSERT, UPDATE, DELETE ON *.* TO 'usuario' @'%' ;
01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.17.
#Crear la tabla departamentoCREATE TABLE departamento (
id INT NOT NULL AUTO_INCREMENT,nombre VARCHAR(64) NOT NULL,PRIMARY KEY (id)
) ENGINE=InnoDB; #Crear la tabla empleadoCREATE TABLE empleado (
id INT NOT NULL AUTO_INCREMENT,nombre VARCHAR(64) NOT NULL,sueldo DECIMAL(8,2) NOT NULL,departamentoid INT NOT NULL,PRIMARY KEY (id),FOREIGN KEY (departamentoid) REFERENCES departamento(id) ON DELETE CASCADE
) ENGINE=InnoDB;
1.2.3.4.5.6.
7.
#Insertar departamentosINSERT INTO departamento (nombre) VALUES ( 'SISTEMAS' );INSERT INTO departamento (nombre) VALUES ( 'CONTABILIDAD' );INSERT INTO departamento (nombre) VALUES ( 'VENTAS' );#Insertar empleado AdministradorINSERT INTO empleado (nombre, sueldo, departamentoid) values ( 'Administrador' ,
1500, 1);COMMIT;
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
2 de 9 05/04/2013 16:53
Cómo instalar MySQL Server en un
servidor Ubuntu
Un poco de Swing usando JTable,
DefaultComboBoxModel,
AbstractTableModel
Código Java para imprimir en la
impresora predeterminada
Cómo instalar Apache HTTP Server 2 en
Ubuntu Server
Cómo instalar Apache Tomcat 6 en
Ubuntu Server
Cómo instalar Subversion en Ubuntu
Server
Cómo eliminar un salto de línea LF(Line
feed, '\n', 0x0A, 10 en decimal) en los
datos de una columna de Oracle
Instalación y configuración de Maven en
Windows
Cómo ejecutar el emulador de Android
en Windows 7
Utilización del método printf para
imprimir en consola columnas espaciadas
Links
Agile Alliance
DZone
Open Source Software in Java
The Server Side
Sun Developers Network (SDN)
Tour de Flex (Flex and AIR Examples)
Martin Fowler (O-O and Agile Influencer)
James Gosling (Father of Java)
iconsPedia
Tesis de Grado EPN
Maven Repository
Live Traffic Feed
de datos como objetos. En el paquete com.blogspot.ingmmurillo.domain crearemos los modelos
(AbstractTableModel y DefaultComboBoxModel ) y en el paquete crearemos un formulario para visualizar los
datos.
Diseño del Formulario
Usando Swing crearemos el siguiente formulario (JFrame ):
En el formulario se cargarán los datos de departamentos extrayendo de la base de datos y se podrá registrar nuevos
empleados o eliminarlos. También se podrá visualizar los datos de la base de datos en un componente JTable y se
refrescarán conforme se vaya agregando o eliminando empleados.
Clases de Dominio
Estas clases son POJOs y representan la estructura de las tablas en objetos. Se las creará en el paquete
com.blogspot.ingmmurillo.domain
01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.
package com.blogspot.ingmmurillo.domain; public class Departamento { private int id;private String nombre;
public int getId() {return id;
} public String getNombre() {return nombre;
} public void setId( int id) {this.id = id;
} public void setNombre(String nombre) {this.nombre = nombre;
}
@Overridepublic String toString() {
// TODO Auto-generated method stubreturn nombre;
}}
01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.
package com.blogspot.ingmmurillo.domain; public class Empleado { private int id;private String nombre;private double sueldo;private Departamento departamento;
public int getId() {return id;
} public String getNombre() {return nombre;
} public double getSueldo() {return sueldo;
} public void setId( int id) {this.id = id;
} public void setNombre(String nombre) {this.nombre = nombre;
} public void setSueldo( double sueldo) {
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
3 de 9 05/04/2013 16:53
Visitas
Seguidores
Modelos para el ComboBox y la Tabla
Live Traffic Feed
A visitor from Santiago,
Region Metropolitana
viewed "Mauricio
Murillo: Cómo eliminar
un salto de línea LF(Line
feed, '\n', 0x0A, 10 en
decimal) en los datos de
una columna de Oracle" 1
min ago
A visitor from Maracaibo,
Zulia viewed "Mauricio
Murillo: Un poco de
Swing usando JTable,
DefaultComboBoxModel,
AbstractTableModel" 12
mins ago
A visitor from Maracaibo,
Zulia viewed "Mauricio
Murillo: Un poco de
Swing usando JTable,
DefaultComboBoxModel,
AbstractTableModel" 13
mins ago
A visitor from Santiago,
Region Metropolitana
viewed "Mauricio
Murillo: Cómo crear un
proyecto de GWT usando
el arquetipo de Maven"
13 mins ago
A visitor from Babahoyo,
Los Rios viewed
"Mauricio Murillo: Cómo
instalar MySQL Server en
un servidor Ubuntu" 15
mins ago
A visitor from Babahoyo,
Los Rios viewed
"Mauricio Murillo: Cómo
instalar MySQL Server en
un servidor Ubuntu" 17
mins ago
A visitor from Lima
viewed "Mauricio
Murillo: Cómo subir el
número de sesiones y
procesos en Oracle 10g
sobre Linux" 23 mins ago
A visitor from Lima
9 4 1 5 0
31.32.33.34.35.36.37.38.39.40.41.42.
this.sueldo = sueldo;}
public Departamento getDepartamento() {return departamento;
} public void setDepartamento(Departamento departamento) {this.departamento = departamento;
} }
01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.
package com.blogspot.ingmmurillo.model;public class ModeloComboBoxDepartamento extends DefaultComboBoxModel { private Vector<Departamento> departamentos;private static final String JDBC_URL = "jdbc:mysql://localhost:3306/test" ;private static final String JDBC_USUARIO = "usuario" ;private static final String JDBC_CLAVE = "prueba" ;
public ModeloComboBoxDepartamento() {
departamentos = new Vector<Departamento>();try {
refrescarDatos();} catch (SQLException e) {
System.err.println(e);}
} public int getSize() {return departamentos.size();
} public Object getElementAt( int index) {return departamentos.get(index);
} private void refrescarDatos() throws SQLException {
Connection conexion = null;Statement st = null;ResultSet rs = null;try {
MysqlDataSource dataSource = new MysqlDataSource();dataSource.setUrl(JDBC_URL);dataSource.setUser(JDBC_USUARIO);dataSource.setPassword(JDBC_CLAVE);
conexion = dataSource.getConnection();st = conexion.createStatement();rs = st.executeQuery( "select id, nombre from departamento" );
while (rs.next()) {
Departamento dep = new Departamento();dep.setId(rs.getInt( "id" ));dep.setNombre(rs.getString( "nombre" ));departamentos.add(dep);
}} catch (SQLException e) {
System.err.println(e);} finally {if (rs != null) {
rs.close();}
if (st != null) {
st.close();}
if (conexion != null) {
conexion.close();}
}}
}
001.002.003.004.005.006.007.008.009.010.011.012.013.014.015.016.017.018.019.020.021.022.023.024.025.
package com.blogspot.ingmmurillo.model;public class ModeloTablaEmpleados extends AbstractTableModel { private Vector<String> columnas;private Vector<Empleado> filas;private static final String JDBC_URL = "jdbc:mysql://localhost:3306/test" ;private static final String JDBC_USUARIO = "usuario" ;private static final String JDBC_CLAVE = "prueba" ;
public ModeloTablaEmpleados(Vector<String> columnas) {this.columnas = columnas;filas = new Vector<Empleado>();try {
refrescarDatos();} catch (SQLException e) {
System.err.println(e);}
}
public int getRowCount() {return filas.size();
} public int getColumnCount() {
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
4 de 9 05/04/2013 16:53
Google Friend Connect
Miembros (11)
¿Ya eres miembro? Iniciar sesión
026.027.028.029.030.031.032.033.034.035.036.037.038.039.040.041.042.043.044.045.046.047.048.049.050.051.052.053.054.055.056.057.058.059.060.061.062.063.064.065.066.067.068.069.070.071.072.073.074.075.076.077.078.079.080.081.082.083.084.
085.086.087.088.089.090.091.092.093.094.095.096.097.098.099.100.101.102.103.104.105.106.107.108.109.110.111.112.113.114.115.116.117.118.119.120.121.122.123.124.125.126.127.128.129.130.
131.
return columnas.size();}
public Object getValueAt( int rowIndex, int columnIndex) {
Empleado emp = filas.get(rowIndex); switch (columnIndex) {case 0:return emp.getId();
case 1:return emp.getNombre();
case 2:return emp.getSueldo();
case 3:return emp.getDepartamento().getNombre();
} return emp;
} public String getColumnName( int column) {return columnas.get(column);
} public void agregarEmpleado(Empleado emp) {
try {
insertarEmpleadoBDD(emp);refrescarDatos();
} catch (SQLException e) {System.err.println(e);
}
} public void eliminarEmpleado( int rowIndex) {try {
Empleado emp = filas.get(rowIndex);eliminarEmpleadoBDD(emp);refrescarDatos();
} catch (SQLException e) {System.err.println(e);
}}
private void refrescarDatos() throws SQLException {
Connection conexion = null;Statement st = null;ResultSet rs = null;try {
MysqlDataSource dataSource = new MysqlDataSource();dataSource.setUrl(JDBC_URL);dataSource.setUser(JDBC_USUARIO);dataSource.setPassword(JDBC_CLAVE);
conexion = dataSource.getConnection();st = conexion.createStatement();rs = st.executeQuery( "select e.id as id, e.nombre as nombre, e.sueldo as
sueldo, e.departamentoid as depid, d.nombre as depa rtamento from empleadoe, departamento d where e.departamentoid = d.id" );
filas.clear();
while (rs.next()) {
Empleado emp = new Empleado();emp.setId(rs.getInt( "id" ));emp.setNombre(rs.getString( "nombre" ));emp.setSueldo(rs.getDouble( "sueldo" ));Departamento dep = new Departamento();dep.setId(rs.getInt( "depid" ));dep.setNombre(rs.getString( "departamento" ));emp.setDepartamento(dep);filas.add(emp);
}fireTableDataChanged();
} catch (SQLException e) {System.err.println(e);
} finally {if (rs != null) {
rs.close();}
if (st != null) {
st.close();}
if (conexion != null) {
conexion.close();}
}}
private void insertarEmpleadoBDD(Empleado emp) throws SQLException {
Connection conexion = null;PreparedStatement st = null;
try {
MysqlDataSource dataSource = new MysqlDataSource();dataSource.setUrl(JDBC_URL);dataSource.setUser(JDBC_USUARIO);dataSource.setPassword(JDBC_CLAVE);
conexion = dataSource.getConnection();st = conexion
.prepareStatement( "INSERT INTO empleado (nombre, sueldo, departamento id)values (?, ?, ?)" );
st.setString( 1, emp.getNombre());
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
5 de 9 05/04/2013 16:53
Clase de Presentación
132.133.134.135.136.137.138.139.140.141.142.143.144.145.146.147.148.149.150.151.152.153.154.155.156.157.158.159.160.161.162.163.164.165.166.167.168.169.170.171.172.173.174.175.176.177.178.179.180.181.182.183.
st.setDouble( 2, emp.getSueldo());st.setInt( 3, emp.getDepartamento().getId());
st.executeUpdate();
fireTableDataChanged();
} catch (SQLException e) {System.err.println(e);
} finally {
if (st != null) {st.close();
}
if (conexion != null) {conexion.close();
}}
} private void eliminarEmpleadoBDD(Empleado emp) throws SQLException {
Connection conexion = null;PreparedStatement st = null;
try {
MysqlDataSource dataSource = new MysqlDataSource();dataSource.setUrl(JDBC_URL);dataSource.setUser(JDBC_USUARIO);dataSource.setPassword(JDBC_CLAVE);
conexion = dataSource.getConnection();st = conexion.prepareStatement( "DELETE FROM empleado WHERE id = ?" );st.setInt( 1, emp.getId());st.executeUpdate();
fireTableDataChanged();
} catch (SQLException e) {System.err.println(e);
} finally {
if (st != null) {st.close();
}
if (conexion != null) {conexion.close();
}}
} }
001.002.003.004.005.006.007.008.009.010.011.012.013.014.015.016.017.018.019.020.021.022.023.024.025.026.027.028.029.030.031.032.033.034.035.036.037.038.039.040.041.042.043.044.045.046.047.048.049.050.051.
package com.blogspot.ingmmurillo.view; public class FrameEmpleado extends JFrame { private JLabel etiquetaNombre;private JLabel etiquetaSueldo;private JLabel etiquetaDepartamento;
private JTextField campoTextoNombre;private JTextField campoTextoSueldo;private JComboBox comboBoxDepartamento;
private JButton botonAgregar;private JButton botonEliminar;
private JScrollPane panelDatosEmpleado;private JTable tablaDatosEmpleado;
private ModeloComboBoxDepartamento modeloComboboxDeps;private ModeloTablaEmpleados modeloTablaEmps;
public FrameEmpleado() {
init();}
public static void main(String[] args) {
FrameEmpleado frame = new FrameEmpleado();frame.setVisible( true);
} public void init() {
// Titulo de la pantallasetTitle( "Empleado" );// Dimensiones de la pantallasetSize( 430 , 500 );// Operacion de cerrarsetDefaultCloseOperation(EXIT_ON_CLOSE);// Centrar el frame en el centro de pantallasetLocationRelativeTo( null);// Asignar el Layout a null para posicionar el form ulario en el centro// de la pantallasetLayout( null);setResizable( false);
// Creacion de los controlesetiquetaNombre = new JLabel( "Nombre : " );etiquetaNombre.setLocation( 10, 10);etiquetaNombre.setSize( 100 , 20);
etiquetaSueldo = new JLabel( "Sueldo :" );etiquetaSueldo.setLocation( 10, 50);
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
6 de 9 05/04/2013 16:53
Aplicación Final
052.053.054.055.056.057.058.059.060.061.062.063.064.065.066.067.068.069.070.071.072.073.074.075.076.077.078.079.080.081.082.083.084.085.086.087.088.089.090.091.092.093.094.095.096.097.098.099.100.101.102.103.104.105.106.107.108.109.110.111.112.113.114.115.116.117.118.119.120.121.122.123.124.125.126.127.128.129.
etiquetaSueldo.setSize( 100 , 20);
etiquetaDepartamento = new JLabel( "Departamento :" );etiquetaDepartamento.setLocation( 10, 90);etiquetaDepartamento.setSize( 100 , 20);
campoTextoNombre = new JTextField();campoTextoNombre.setLocation( 120 , 10);campoTextoNombre.setSize( 120 , 20 );
campoTextoSueldo = new JTextField();campoTextoSueldo.setLocation( 120 , 50);campoTextoSueldo.setSize( 120 , 20 );
modeloComboboxDeps = new ModeloComboBoxDepartamento();comboBoxDepartamento = new JComboBox(modeloComboboxDeps);comboBoxDepartamento.setLocation( 120 , 90);comboBoxDepartamento.setSize( 120 , 20);
botonAgregar = new JButton( "Agregar" );botonAgregar.setLocation( 320 , 10 );botonAgregar.setSize( 80, 20 );
botonEliminar = new JButton( "Eliminar" );botonEliminar.setLocation( 320 , 50);botonEliminar.setSize( 80, 20);
Vector<String> columnasTablaEmpleado = new Vector<String>();columnasTablaEmpleado.add( "ID" );columnasTablaEmpleado.add( "NOMBRE");columnasTablaEmpleado.add( "SUELDO");columnasTablaEmpleado.add( "DEPARTAMENTO");
modeloTablaEmps = new ModeloTablaEmpleados(columnasTablaEmpleado);tablaDatosEmpleado = new JTable(modeloTablaEmps);panelDatosEmpleado = new JScrollPane(tablaDatosEmpleado);panelDatosEmpleado.setLocation( 10, 140 );panelDatosEmpleado.setSize( 400 , 300 );
// Agregación de los controles al frameadd(etiquetaNombre);add(etiquetaSueldo);add(etiquetaDepartamento);add(campoTextoNombre);add(campoTextoSueldo);add(comboBoxDepartamento);add(botonAgregar);add(botonEliminar);add(panelDatosEmpleado);
// Eventos de los botonesbotonAgregar.addActionListener( new ActionListener() {
@Overridepublic void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stubEmpleado emp = new Empleado();emp.setNombre(campoTextoNombre.getText());emp.setSueldo(Double.valueOf(campoTextoSueldo.getTe xt()));Departamento dep = (Departamento) comboBoxDepartame nto
.getSelectedItem();emp.setDepartamento(dep);modeloTablaEmps.agregarEmpleado(emp);
}});
botonEliminar.addActionListener( new ActionListener() {
@Overridepublic void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stubmodeloTablaEmps.eliminarEmpleado(tablaDatosEmpleado
.getSelectedRow());}
});
}}
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
7 de 9 05/04/2013 16:53
Entrada más reciente Entrada antigua
Recomendaciones
En ésta publicación he expuesto el código para usar los modelos de datos para los ComboBox en un JComboBox y para
una tabla en una JTable. Cabe destacar que la lógica de conexión a la base de datos que se hace en los 2 modelos no
debería estar ahí. En una aplicación real, es importante definir una clase que se encargue de manejar las conexiones
a la base de datos y ejecutar las instrucciones SQL; o también se podría usar un ORM como Hibernate.
Etiquetas: AbstractTableModel, Connection, DefaultComboBoxModel, Hibernate, Java, Java Swing, JDBC,
JFC, JScrollPane, JTable, POJO, ResultSet, SQL, Statement
3 comentarios:
henry pb dijo...
11/09/2012 12:49:00 p.m.
Ordenado, Didactico y muy Pedagogico.
Excelente documento Mauricio.Es de gran ayuda para mi ya que me estoy iniciando en el Desarrollo de Sistemas
de Información utilizando el lenguaje de programación Java -Saludos-
Yasmany Castillo dijo...
3/28/2013 08:30:00 a.m.
Bastante bueno, he implementado los metodos y hasta ahora todo bien, pero al correr la aplicación y tratar de
insertar en la base de datos me da el siguiente error:
Cannot add or update a child row: a foreign key constraint fails (`qxclinica/usuarios`, CONSTRAINT
`fk_Usuarios_Perfiles` FOREIGN KEY (`idPerfiles`) REFERENCES `perfiles` (`idPerfiles`) ON DELETE CASCADE)
Me podria ayudar, [email protected]
Yasmany Castillo dijo...
3/28/2013 08:32:00 a.m.
El ejemplo es bastante claro, y explicativo. Lo estoy implementando en una aplicación pero al tratar de insertar
me tira la siguiente excepción.
Cannot add or update a child row: a foreign key constraint fails (`qxclinica/usuarios`, CONSTRAINT
`fk_Usuarios_Perfiles` FOREIGN KEY (`idPerfiles`) REFERENCES `perfiles` (`idPerfiles`) ON DELETE CASCADE).
Por que esto?
Publicar un comentario en la entrada
Página principal
Suscribirse a: Enviar comentarios (Atom)
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
8 de 9 05/04/2013 16:53
Copyright @ 2009 - Maur icio Mur i llo
Crys tal B lue Theme by Hos ting ITrus t.com and brought you by Ray Creations
Mauricio Murillo: Un poco de Swing usando JTable, DefaultComboB... http://ingmmurillo.blogspot.com/2011/04/un-poco-de-swing-usando-jtab...
9 de 9 05/04/2013 16:53