Karta w JTabbedPane nie odzwierciedla zmian w naciśnięciu przycisku

W zakładce mojego GUI użytkownik może edytować imię i nazwisko pracownika. Nazwa służy również jako etykieta karty, więc po potwierdzeniu zmiany karta powinna zostać zaktualizowana, aby odzwierciedlić tę zmianę, a nowe dane zostaną zapisane w pliku danych.

Pracownicy są zapisani w aHashMap w klasieEmployees. Karty są zapełniane przez iterację poprzezArrayList<String> nazw pracowników, które uzyskuje się od wywołania metodyEmployees.getNames(). Z GUI użytkownik może wpisać nową nazwę, a następnie nacisnąć przycisk zmiany nazwy. PrzyciskiActionListener wywołuje metodęchangeName(), który zastępuje starą nazwę nową nazwą wHashMap i aktualizuje plik danych.

Działa to poprawnie po raz pierwszy, gdy użytkownik chce zmienić nazwę pracownika, ale kolejne zmiany powodują błąd. Wygląda na to, żeJPanel który zawieraJTextFields (widziećgetEmployeeInfoPanel() poniżej) nie aktualizuje parametruname. Ten parametr jest aktualną nazwą pracownika, podczas gdy nowa nazwa pochodzi odJTextField.

Przykład ilustrujący ten problem znajduje się poniżej. Zasadniczo kroki są następujące:

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.

Hierarchia tego konkretnego ekranu to:

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

A oto odpowiedni kod z 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;
    }
}

a oto kod klasy pracowników, który zmienia 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.");
    }
}

Oto przykład. Pierwszy zrzut ekranu pochodzi z chwili uruchomienia programu; nazwiska pracowników są wypełniane w odpowiednich zakładkach. Drugi zrzut ekranu pojawia się po próbie zmiany nazwiska pracownika. Jak widać, etykieta karty nie uległa zmianie, do której przyjąłem połączenievalidate() zrobiłby.

(Przed)

(Po naciśnięciu przycisku)

I na koniec, wyjście, które dwukrotnie naciska przycisk zmiany nazwy, pokazuje, że nazwa została zmieniona na liście 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