Pregunta

I have a Swing desktop application with a JTable. There are no problems when adding rows to the JTable. I can also sort (using JTable.autoCreateRowSorter) and then delete the row (using convertRowIndexToModel) smoothly.

I do run into problems when I search in a text box where the JTable updates to show only the rows that contain the query. When I try to delete a row after typing in a search term, weird things start happening:

public class EmployeeRecords extends javax.swing.JFrame {

ArrayList<Employee> employees = new ArrayList <Employee> ();

...
private void search(String query) {
    //Create new table sorter for the table
    TableRowSorter sorter = new TableRowSorter(employeeTable.getModel());
    //Add row filter to the tablerowsorter (regex)
    sorter.setRowFilter(RowFilter.regexFilter("(?i).*\\Q"+query+"\\E.*") );
    //Apply the results to the output table
    employeeTable.setRowSorter(sorter);
}

private void deleteButtonActionPerformed() {
    //Get the index of the employee to delete
    int employee = employeeTable.convertRowIndexToModel(
            employeeTable.getSelectedRow());

    employees.remove(employee); //This is where the IndexOutOfBoundsException occurs

    refreshTable();
}

/**
 * Refreshes the employee table. Uses the "employees" class array list to
 * populate the rows.
 */
private void refreshTable() {
    //Delete all the rows in the table
    DefaultTableModel tbm = (DefaultTableModel) employeeTable.getModel();
    for (int i=employeeTable.getRowCount()-1; i >= 0; i--) {
        tbm.removeRow(i);
    }

    //For every employee
    for (int i=0; i < employees.size(); i++) {
        //Add the employee's data to a table row
        tbm.addRow(employees.get(i).getData());
    }
}
}

I will try to delete a row, and sometimes it duplicates the row I wanted to delete. Other times I get an IndexOutOfBoundsException, probably because the indeces are messed up.

I did not understand the solution to someone with the same problem as I don't really know that much about Swing Timers and such.

I also made sure to convert the row indeces to model as suggested in this question.

Any ideas as to how to fix this?

UPDATE: This is a basic screenshot of what is happening. enter image description here Search for "a" and "a" and "aa" show up: enter image description here

And when I select "a" and click Delete Selected this is the result: enter image description here

Now if I try to keep deleting the "aa"'s then I eventually get a IndexOutOfBoundsException.

UPDATE 2: Here is the employee class:

public class Employee {

//Class fields
Integer employeeIdNumber;
String firstName, lastName, startDate;
Double annualSalary;

/* Constructor for the Employee object */
public Employee(Integer employeeIdNumber, String firstName, String lastName, 
        Double annualSalary, String startDate) {

    //Assign paramters to class fields
    this.employeeIdNumber = employeeIdNumber;
    this.firstName = firstName;
    this.lastName = lastName;
    this.annualSalary = annualSalary;
    this.startDate = startDate;
}

/**
 * Gets the data for the employee (ID, firstname, lastname, annual salary,
 * and start date, in that order)
 * 
 * @return an Object[] of the abovementioned employee data.
 */
public Object[] getData() {
    return new Object[] {
        employeeIdNumber,
        firstName,
        lastName,
        annualSalary,
        startDate
    };
}
}

FIX (thanks to camickr): I changed the following code for the delete button

private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             

    DefaultTableModel tbm = (DefaultTableModel) employeeTable.getModel();
    //Get the index of the employee to delete
    int employee = employeeTable.convertRowIndexToModel(
            employeeTable.getSelectedRow());

    //Delete the row directly
    tbm.removeRow(employee);
    //as well as delete the employee from the array
    employees.remove(employee);
} 
¿Fue útil?

Solución

Not sure I understand your design. You have a DefaultTableModel and you also have an ArrayList that contains your employees.

The employee data should be stored in the TableModel. There should be no need to recreate the TableModel as you should just remove the row from the model and the table will repaint itself.

Also, as a note for when using the DefaultTableModel you just use the following to remove all the rows:

model.setRowCount(0);

Otros consejos

While deleting all rows in refreshTable method, try by changing logic

while(employeeTable.getRowCount() > 0) {
    tbm.removeRow(0);
}

This ensures that you won't get a IndexOutOfBoundsException. Also might solve the other problem of duplicate row display as well.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top