Tabulação no JTabbedPane não reflete as alterações no botão pressionado

Dentro de uma guia da minha GUI, o usuário tem permissão para editar o nome de um funcionário. O nome também serve como rótulo da guia, portanto, quando a alteração é confirmada, a guia deve ser atualizada para refletir essa alteração e os novos dados são gravados em um arquivo de dados.

Os funcionários são armazenados em umHashMap na aulaEmployees. As guias são preenchidas por uma iteração por meio deArrayList<String> dos nomes dos funcionários, que é obtido ao chamar o métodoEmployees.getNames(). Na GUI, o usuário pode digitar um novo nome e pressionar o botão de mudança de nome. Os botõesActionListener chama o métodochangeName(), que substitui o nome antigo pelo novo nome noHashMap e atualiza o arquivo de dados.

Isso funciona corretamente na primeira vez que um usuário deseja alterar o nome do funcionário, mas as alterações subsequentes geram um erro. Parece que oJPanel que contém oJTextFields (VejogetEmployeeInfoPanel() abaixo) não está atualizando o parâmetroname. Este parâmetro é o nome atual do funcionário, enquanto o novo nome é obtido doJTextField.

Um exemplo para ilustrar esse problema está abaixo. Essencialmente, os passos são:

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.

A hierarquia desta tela em particular é:

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

E aqui está o código relevante da 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;
    }
}

e aqui está o código da classe Funcionários que altera o 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.");
    }
}

Aqui está um exemplo. A primeira captura de tela é de quando o programa é iniciado; os nomes dos funcionários são preenchidos nas guias apropriadas. A segunda captura de tela é depois de tentar alterar o nome do funcionário. Como você pode ver, o rótulo da guia não mudou, e eu assumi a chamada paravalidate() faria.

(Antes)

(Depois de pressionar o botão)

E, finalmente, a saída que pressiona o botão do nome da alteração produz duas vezes, mostrando que o nome foi alterado na 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.

questionAnswers(1)

yourAnswerToTheQuestion