Reputation: 450
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. Search for "a" and "a" and "aa" show up:
And when I select "a" and click Delete Selected this is the result:
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);
}
Upvotes: 3
Views: 3208
Reputation: 324098
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);
Upvotes: 3
Reputation: 9158
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.
Upvotes: 0