[SOLUCIONADO] JTable Agregando filas dentro del for no funciona

Iniciado por 2Fac3R, Mayo 13, 2015, 08:38:47 PM

Tema anterior - Siguiente tema

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

Mayo 13, 2015, 08:38:47 PM Ultima modificación: Mayo 14, 2015, 04:49:21 PM por blackdrake
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

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

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


Para pruebas, pero la parte que realmente ocupo es:
Código: java

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

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

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!
Sólo el conocimiento te hace libre.

Hola,

Primero dos cosas:


  • Haz tu código lógico, es decir, ese for es una mezcla de variables que generan confusión para el lector.
  • Interpreta las excepciones.

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
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
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.

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

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));


}

}



Gracias por la ayuda!  ;D
Zalu2
Sólo el conocimiento te hace libre.

Mayo 14, 2015, 12:47:29 PM #3 Ultima modificación: Mayo 14, 2015, 12:52:15 PM por Gus Garsaky
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.