La pestaña en JTabbedPane no refleja los cambios al presionar un botón

Dentro de una pestaña de mi GUI, el usuario puede editar el nombre de un empleado. El nombre también sirve como etiqueta de la pestaña, por lo que cuando se confirma el cambio, la pestaña debe actualizarse para reflejar este cambio y los nuevos datos se escriben en un archivo de datos.

Los empleados se almacenan en unHashMap en la claseEmployees. Las pestañas se rellenan iterando a través de unArrayList<String> de los nombres de los empleados, que se obtiene de llamar al métodoEmployees.getNames(). Desde la GUI, el usuario puede escribir un nuevo nombre y luego presionar el botón cambiar nombre. Los botonesActionListener llama al métodochangeName(), que reemplaza el nombre antiguo con el nombre nuevo en elHashMap y actualiza el archivo de datos.

Esto funciona correctamente la primera vez que un usuario desea cambiar el nombre del empleado, pero los cambios posteriores producen un error. Parece que elJPanel que contiene elJTextFields (vergetEmployeeInfoPanel() abajo) no está actualizando el parámetroname. Este parámetro es el nombre actual del empleado, mientras que el nuevo nombre se obtiene de laJTextField.

A continuación se muestra un ejemplo para ilustrar este problema. Esencialmente, los pasos son:

1. old name = Mary is provided when the program starts
2. User changes name in JTextField, so oldName = Mary and newName = Mary S.
3. At this point, oldName should update to Mary S. as it is the new key.
   However, oldName remains as Mary so the HashMap cannot be  updated again.

La jerarquía de esta pantalla en particular es:

JFrame (entire application)
   |
    -- JPanel EmployeesPanel (this screen)
   |     |
   |      -- JPanel (for custom menu bar)
   |     |
   |      -- JTabbedPane (one tab for each employee)
   |             |
   |              -- JPanel (contains JLabels, JTextField, etc for this employee)
   |
    -- .....

Y aquí está el código relevante de la GUI:

public class EmployeesPanel {
    private JTabbedPane pane;
    private Employees employees;
    ...
    public EmployeesPanel(JPanel panel, Container cards) {
        ...
        pane = new JTabbedPane();
        getEmployees();
    }

    private void getEmployees() {
                    ...
        employees = new Employees(properties, EMPLOYEES_TXT);
        //ArrayList of all employees' names
        names = employees.getNames();
        for(String name : names) {
            pane.addTab(name, getEmployeeInfoPanel(name));
        }
        pane.addTab("NEW EMPLOYEE", addEmployeePanel());
    }

    public JPanel addEmployeePanel() {
        ...
    }

    private JPanel getEmployeeInfoPanel(final String name) throws EmployeeException {
        JPanel infoPanel = new JPanel();
        infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.PAGE_AXIS));

        JLabel nameLabel = new JLabel("Employee name");
        JLabel wageLabel = new JLabel("Employee wage");
        final JTextField nameField = new JTextField(name, 30);
        final JTextField wageField = new JTextField(employees.getWage(name).toString(), 30);

        JButton changeNameButton = new JButton("CHANGE NAME");
        JButton changeWageButton = new JButton("CHANGE WAGE");

        changeNameButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                try {
                    String newName = nameField.getText();
                    employees.changeName(name, newName);
                    panel.validate();
                } catch (EmployeeException e) {
                    // TODO create popup warning
                }
            }
        });
        ...
        return infoPanel;
    }
}

y aquí está el código de la clase Empleados que cambia el HashMap:

public void changeName(String oldName, String newName) throws EmployeeException {
    System.out.println("old name = " + oldName + ", new name = " + newName);
    if(employees.containsKey(oldName)) {
        BigDecimal wage = employees.get(oldName);
        employees.remove(oldName);
        employees.put(newName, wage);
        names.remove(oldName);
        names.add(newName);
        prop.remove(oldName);
        prop.setProperty(newName, wage.toString());
        saveProperties();
        System.out.println(names);
    } else {
        throw new EmployeeException("Could not change name because employee does not exist.");
    }
}

Aquí hay un ejemplo. La primera captura de pantalla es de cuando se inicia el programa; los nombres de los empleados se rellenan en las pestañas apropiadas. La segunda captura de pantalla es después de intentar cambiar el nombre del empleado. Como puede ver, la etiqueta de la pestaña no ha cambiado, por lo que asumí la llamada avalidate() haría.

(Antes de)

(Después de presionar el botón)

Y finalmente, la salida que al presionar dos veces el botón para cambiar el nombre, muestra que el nombre ha sido cambiado en el ArrayList:

old name = Mary, new name = Mary S.
[Jane, Bob, Sue, Mary S.]
old name = Mary, new name = Mary S.
653647 [AWT-EventQueue-0] ERROR employees.EmployeeException - Could not change name because employee does not exist.

Respuestas a la pregunta(1)

Su respuesta a la pregunta