swing - filtrar - organizar jtable
Después de agregar un TableRowSorter, agregar valores al modelo causa java.lang.IndexOutOfBoundsException: rango no válido (3)
Después de agregar un TableRowSorter a una tabla y su modelo correspondiente, cualquier adición correspondiente específicamente en tableros de fuego incluye excepciones de causa insertada. De las pruebas se desprende que GetRowCount () está devolviendo un valor más allá del rango de modelos. Sin embargo, no tiene sentido para mí cómo continuar agregando valores a la tabla después de que se haya agregado un clasificador o filtro?
Como ejemplo, configuré el filtro de fila antes de agregar algo a la tabla y luego agregué un valor a la tabla con las siguientes llamadas en mi modelo:
this.addRow(row, createRow(trans,row));
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());
El recuento de filas es del tamaño 1 y se lanza la excepción:
java.lang.IndexOutOfBoundsException: Invalid range
at javax.swing.DefaultRowSorter.checkAgainstModel(Unknown Source)
at javax.swing.DefaultRowSorter.rowsInserted(Unknown Source)
at com.gui.model
Si hago los mismos pasos sin agregar primero el clasificador todo está bien. Supuse que posiblemente tenía que notificar al modelo que el clasificador podría haber realizado cambios y probado lo siguiente, pero aún así devuelve una excepción:
this.addRow(row, createRow(trans,row));
this.fireTableStructureChanged()
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());
Incluso traté de notificar al clasificador dentro del modelo que se ha agregado un valor al modelo antes de invocar fuego como a continuación, pero también falla:
this.addRow(row, createRow(trans,row));
if(sorter.getRowFilter() != null){
//if a sorter exists we are in add notify sorter
sorter.rowsInserted(getRowCount(), getRowCount());
}
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());
Por último, he codificado el FireTableRowsInsterted (0,0) y no arroja ninguna excepción. Pero nada se agrega a la mesa? Entonces, sé que definitivamente es algún tipo de problema con OutOfBounds. He mirado por todas partes y parece que no puedo encontrar la respuesta. Si alguien tiene alguna idea de cómo se supone que debe funcionar, será muy útil. Aquí hay un código que establece el clasificador dentro de jpanel:
messageTable.setRowSorter(null);
HttpTransactionTableModel m = getTransactionTableModel();
final int statusIndex = m.getColIndex("status");
RowFilter<Object,Object> startsWithAFilter = new RowFilter<Object,Object>() {
public boolean include(Entry<? extends Object, ? extends Object> entry) {
for(char responseCode:responseCodes)
{
if (entry.getStringValue(statusIndex).startsWith(Character.toString(responseCode))) {
return true;
}
}
// None of the columns start with "a"; return false so that this
// entry is not shown
return false;
}
};
m.sorter.setRowFilter(startsWithAFilter);
messageTable.setRowSorter(m.sorter);
Aquí hay un código dentro de mi modelo que agrega valor al modelo:
public void update(Observable o, Object evt) {
if (evt instanceof ObservableEvent<?>) {
ObservableEvent<?> event = (ObservableEvent<?>) evt;
if (event.getElement() instanceof HttpTransaction) {
HttpTransaction trans = (HttpTransaction) event.getElement();
// handle adding of an element
if (event.getAction() == PUT) {
if (includeTransaction(trans)) {
// handle request elements
if (trans.getRequest() != null && idMap.get(trans.getID()) == null) {
idMap.put(trans.getID(), count++);
// transactionManager.save(trans);
int row = idMap.get(trans.getID());
this.addRow(row, createRow(trans,row));
if(sorter.getRowFilter() != null){
sorter.rowsInserted(getRowCount(), getRowCount());
}
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());
}
Entonces, por ahora, parece que si revisa su modelo si está actualmente en modo de clasificación y si es el caso, solo llame a la actualización en el modelo de clasificación. De lo contrario, llame a las actualizaciones de incendios modelo normal, todo parece funcionar hasta el momento. Todavía estoy abierto para mejores formas de manejar esto:
if(sorter.getRowFilter() != null){
sorter.modelStructureChanged();
}
else
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());
Volví y lo miré mejor después de ver el comentario de Kleopatra. Estaba cambiando mi TableModel después de crear un RowSorter, pero antes de conectar el RowSorter a JTable. Aquí hay un ejemplo que muestra el problema que estaba teniendo.
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;
import java.util.ArrayList;
import java.util.List;
public class TestTableMain {
public static void main(String[] args) {
new TestTableMain();
}
public TestTableMain() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
buildAndShowMainFrame();
}
});
}
private void buildAndShowMainFrame() {
JFrame frame = new JFrame();
JScrollPane scrollPane = new JScrollPane();
TestTableModel model = new TestTableModel();
JTable table = new JTable(model);
TableRowSorter<TestTableModel> rowSorter = new TableRowSorter<>(model);
rowSorter.setRowFilter(null);
model.add("First added item.");
/* The RowSorter doesn''t observe the TableModel directly. Instead,
* the JTable observes the TableModel and notifies the RowSorter
* about changes. At this point, the RowSorter(s) internal variable
* modelRowCount is incorrect. There are two easy ways to fix this:
*
* 1. Don''t add data to the model until the RowSorter has been
* attached to the JTable.
*
* 2. Notify the RowSorter about model changes just prior to
* attaching it to the JTable.
*/
// Uncomment the next line to notify rowSorter that you''ve changed
// the model it''s using prior to attaching it to the table.
//rowSorter.modelStructureChanged();
table.setRowSorter(rowSorter);
scrollPane.setViewportView(table);
frame.setContentPane(scrollPane);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
model.add("Second added item.");
}
private class TestTableModel extends AbstractTableModel {
private List<String> items = new ArrayList<>();
public TestTableModel() {
for(int i=0;i<5;i++) {
add("Item " + i);
}
}
@Override
public int getRowCount() {
return items.size();
}
@Override
public int getColumnCount() {
return 1;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
return items.get(rowIndex);
}
public void add(String item) {
items.add(item);
fireTableRowsInserted(items.size() - 1, items.size() - 1);
}
}
}
Tienes un error de salida por 1. El código correcto para activar el evento es:
this.fireTableRowsInserted(this.getRowCount()-1, this.getRowCount()-1);