Underc0de

Foros Generales => Dudas y pedidos generales => Mensaje iniciado por: 2Fac3R en Mayo 13, 2015, 08:38:47 PM

Título: [SOLUCIONADO] JTable Agregando filas dentro del for no funciona
Publicado por: 2Fac3R en Mayo 13, 2015, 08:38:47 PM
Buenas!  8)

Resulta que tengo que hacer una tabla con valores que tomo de una matriz de adyacencia la cual está en un archivo de textos, todo eso bien, pero cuando trato de ingresar los valores dentro del for (para ir recorriendo todos) no me funciona, pero afuera sí!  :o

Código (java) [Seleccionar]

package practica4;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;

import practica4.Archivo;

public class Table extends JFrame {

public Table() {
Archivo file = new Archivo();
file.Leer3();

Object[][] datos = null;
String[] columnNames = {"Origen","Destino","Peso"};
DefaultTableModel dtm= new DefaultTableModel(datos,columnNames);
final JTable table = new JTable(dtm);

ArrayList<String> ciudades = file.getCitiesMatriz();
ArrayList<String> pesos = file.getPesos();
/*Object[] newRow={"a","b","c"};
dtm.addRow(newRow);*/

for(int j=0, k=0; j<=ciudades.size() ; j++)
{
for(int i=0; i<ciudades.size(); i++,k++)
{
if(ciudades.get(j).equals(ciudades.get(i)))
{
continue;
}
Object[] newRow={"a","b","c"};
dtm.addRow(newRow);

// Agregar nueva fila
/*Object[] newRow={ciudades.get(j),ciudades.get(i),pesos.get(k)};
dtm.addRow(newRow);*/

//System.out.println(ciudades.get(j) + " - " + ciudades.get(i) + "- " + pesos.get(k));


}

}
table.setPreferredScrollableViewportSize(new Dimension(250, 100));
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane, BorderLayout.CENTER);

addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e){System.exit(0);}
});
}
public static void main(String[] args) {
Table frame = new Table();
frame.pack();
frame.setVisible(true);
}
}


Hice la parte:
Código (java) [Seleccionar]

Object[] newRow={"a","b","c"};
dtm.addRow(newRow);


Para pruebas, pero la parte que realmente ocupo es:
Código (java) [Seleccionar]

Object[] newRow={ciudades.get(j),ciudades.get(i),pesos.get(k)};
dtm.addRow(newRow);


Si saco esa parte afuera del for si me funciona, por ejemplo:
Código (java) [Seleccionar]

Object[] newRow={"a","b","c"};
dtm.addRow(newRow);

/*for(int j=0, k=0; j<=ciudades.size() ; j++)
{
for(int i=0; i<ciudades.size(); i++,k++)
{
if(ciudades.get(j).equals(ciudades.get(i)))
{
continue;
}
Object[] newRow={"a","b","c"};
dtm.addRow(newRow);

// Agregar nueva fila
/*Object[] newRow={ciudades.get(j),ciudades.get(i),pesos.get(k)};
dtm.addRow(newRow);

//System.out.println(ciudades.get(j) + " - " + ciudades.get(i) + "- " + pesos.get(k));


}

}*/


El error es el siguiente:
CitarException in thread "main" java.lang.IndexOutOfBoundsException: Index: 6, Size: 6
   at java.util.ArrayList.rangeCheck(Unknown Source)
   at java.util.ArrayList.get(Unknown Source)
   at practica4.Table.<init>(Table.java:32)
   at practica4.Table.main(Table.java:59)

Archivo txt:
Citar
ALEMANIA BELGICA CANADA FRANCIA HOLANDA INGLATERRA
0    5    7    0    6    0   
2    0    0    4    0    3
0    1    6    0    9    7
4    8    0    5    0    0
11    9    0    0    3    2
3    0    8    9    0    0

Método Leer3() de la clase Archivo
Código (java) [Seleccionar]

public void Leer3()
{
try
{
JFileChooser chooser = new JFileChooser();
chooser.showOpenDialog(chooser);
File fileXML = chooser.getSelectedFile();
String path = fileXML.getAbsolutePath();
String linea;

FileInputStream archivo = new FileInputStream(path);
Scanner sc = new Scanner(archivo);
cities_matriz = new ArrayList<String>();
pesos = new ArrayList<String>();

linea = sc.nextLine();
StringTokenizer st0 = new StringTokenizer(linea," ");

while(st0.hasMoreTokens())
{
cities_matriz.add(st0.nextToken());

}



while(sc.hasNextLine()) {
StringTokenizer st = new StringTokenizer(sc.nextLine(),"    ");

while(st.hasMoreTokens())
{
pesos.add(st.nextToken());

}
        }
sc.close();
}
catch(Exception fnfe){
JOptionPane.showMessageDialog(null, "Archivo no seleccionado!.");
}

}


Alguien sabe cuál es el problema? Porqué afuera del for si se crea la tabla y dentro no?

Zalu2!
Título: Re:JTable Agregando filas dentro del for no funciona
Publicado por: Gus Garsaky en Mayo 13, 2015, 11:35:26 PM
Hola,

Primero dos cosas:


El lugar de anidar dos for para ver si la ciudad ya existe, crea un método que haga ello e itera el List con un foreach simple:

Código (java) [Seleccionar]
for(String ciudad : ciudades) {
if(checkIfExists(ciudad)) {
continue;
} else {
Object[] rowToAdd = {"a", "b", "c", "d"};
dm.addRow(rowToAdd);
}
}

/**
* Compara si un valor existe actualmente en la tabla
* @param city ciudad a evaluar si existe
* @return true si existe, false de lo contrario
*/
private boolean checkIfExists(String city) {
boolean exists;
for(int row=0; row<dm.getRowCount(); row++) {
for(int col=0; col<dm.getColumnCount(); col++) {
String currentCity = dm.getValueAt(row, col);
exists = currentCity.equals(city);
}
}
return exists;
}


Ahora, si analizamos la excepción, veremos que dice:

CitarException in thread "main" java.lang.IndexOutOfBoundsException: Index: 6, Size: 6

La excepción java.lang.IndexOutOfBoundsException se lanza cuando se está tratando de acceder a un índice que excede el tamaño de la lista, por lo que, como dicho índice no existe, la VM lanza dicha excepción en tiempo de ejecución.

Ésto, se puede deducir en tu código por que iteras desde 0 hasta N, cuando es  desde 0 hasta N-1:

Código (java) [Seleccionar]
for(int j=0, k=0; j<=ciudades.size() ; j++) { /*...*/ }

El rastreo de pila te indica en qué líneas están tu error. En tu caso dice que el error lógico está en las líneas 32 y 59 (posible redundancia) en la clase Table. Revisa y comentas cómo te fue.
Título: Re:JTable Agregando filas dentro del for no funciona
Publicado por: 2Fac3R en Mayo 14, 2015, 11:19:38 AM
Vaya que se me ha ido el tema del n-1  ::)

En el for no veo donde esté la confusión, simplemente es un for anidado dentro de otro lo cual hace que recorra la lista de ciudades mientras el otro sigue en el mismo, lo cual me permite tomar el valor de ciudades de j para todas las ciudades (donde uso i).

Pienso que no es necesario crear otro método para verificar que la ciudades sean iguales, ya que en 1 linea se puede hacer, pero lo tendré en cuenta.

Se ha solucionado el problema debido a lo que mencionabas del índice, ha quedado así:
Código (java) [Seleccionar]

for(int j=0, k=0; j<ciudades.size() ; j++)
{
for(int i=0; i<ciudades.size(); i++,k++)
{
if(ciudades.get(j).equals(ciudades.get(i)))
{
continue;
}


// Agregar nueva fila
Object[] newRow={ciudades.get(j),ciudades.get(i),pesos.get(k)};
dtm.addRow(newRow);

//System.out.println(ciudades.get(j) + " - " + ciudades.get(i) + "- " + pesos.get(k));


}

}


(http://s28.postimg.org/oafa8xku5/Captura_de_pantalla_2015_05_14_09_15_57.png)
Gracias por la ayuda!  ;D
Zalu2
Título: Re:JTable Agregando filas dentro del for no funciona
Publicado por: Gus Garsaky en Mayo 14, 2015, 12:47:29 PM
Siempre que crees algún código, hazlo lo más limpio y modular posible. Es muy posible que ahora no le veas sentido, pero cuando hagas cosas complejas, si no sigues los principales principios de desarrollo, como DRY, SRP y facilitando el unit testing y otras cosas más importantes en el desarrollo, realmente tu aplicación será pobre desde el punto de vista de escalabilidad y llegará un punto en que se haga inmantenible y tengas que dar la aplicación por muerta, y será una pérdida grande económicamente.

Esos for pueden estructurarse mejor, de manera más limpia. Recuerda que en el mundo real, muchas personas van a ver tu código y éste deberá tener la suficiente calidad como para que lo puedan entender y mantener.

Me alegra que se haya resuelto tu duda. Un saludo.