Вопрос по java, swing, jtabbedpane, user-interface – Вкладка в JTabbedPane не отражает изменения при нажатии кнопки

2

На вкладке моего графического интерфейса пользователю разрешено редактировать имя сотрудника. Имя также служит меткой вкладки, поэтому, когда изменение подтверждается, вкладка должна быть обновлена, чтобы отразить это изменение, и новые данные записываются в файл данных.

Сотрудники хранятся вHashMap в классеEmployees, Вкладки заполняются путем итерацииArrayList<String> сотрудников & apos; имена, которые получаются при вызове методаEmployees.getNames(), Из графического интерфейса пользователь может ввести новое имя и затем нажать кнопку изменения имени. КнопкаActionListener вызывает методchangeName(), который заменяет старое имя новым именем вHashMap и обновляет файл данных.

Это работает правильно, когда пользователь впервые хочет изменить имя сотрудника, но последующие изменения приводят к ошибке. Похоже, чтоJPanel который содержитJTextFields (увидетьgetEmployeeInfoPanel() ниже) не обновляет параметрname, Этот параметр является текущим именем сотрудника, в то время как новое имя получается изJTextField.

Пример для иллюстрации этой проблемы приведен ниже. По сути, следующие шаги:

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.

Иерархия этого конкретного экрана:

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

А вот соответствующий код из графического интерфейса:

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;
    }
}

и вот код из класса Employees, который изменяет 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.");
    }
}

Вот пример. Первый снимок экрана - с момента запуска программы; имена сотрудников вводятся в соответствующие вкладки. Второй снимок экрана - после попытки изменить имя сотрудника. Как вы можете видеть, ярлык вкладки не изменился, и я принял вызовvalidate() сделал бы.

(До)

enter image description here

(После нажатия кнопки)

enter image description here

И, наконец, вывод, который дважды происходит при нажатии кнопки изменения имени, показывает, что имя было изменено в 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.
Ошибка происходит при нажатии кнопки смены имени. Кнопка ActionListener вызывает методchangeName(), который заменяет старое имя сотрудника новым именем. Первый раз он успешно заменяет имя, но не обновляет вкладку, и любые последующие изменения приводят к ошибке. A D
Я собираюсь отредактировать свой вопрос, чтобы, надеюсь, дать больше ясности A D
Если вы устанавливаете заголовок JTabbedPane в соответствии с рекомендациями @trashgod и по-прежнему испытываете проблему, то, боюсь, ваш вопрос и код не показывают достаточно, чтобы угадать проблему. Hovercraft Full Of Eels
Вам необходимо создать и опубликоватьsscce, Весь этот не связанный код - и ваша проблема заключалась в том, что вы просто не звонилиsetTitleAt(), Господь. Hovercraft Full Of Eels
Я не вижу код, в котором происходит ошибка. Hovercraft Full Of Eels

Ваш Ответ

1   ответ
4

setTitleAt() метод.

Приложение: для сравнения, здесьsscce это позволяет несколько изменений.

TabEdit

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;

/**
 * @see http://stackoverflow.com/a/11007109/230513
 */
public class TabEdit extends JPanel {

    private static final int MAX = 5;
    private static final String NAME = "Tab ";
    private final JTabbedPane pane = new JTabbedPane();

    public TabEdit() {
        for (int i = 0; i < MAX; i++) {
            pane.add(NAME + String.valueOf(i), new TabContent(i));
        }
        this.add(pane);
    }

    private class TabContent extends JPanel {

        private TabContent(final int i) {
            final JTextField jtf = new JTextField(
                "Please edit the name of " + NAME + String.valueOf(i));
            this.add(jtf);
            jtf.addActionListener(new AbstractAction() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    pane.setTitleAt(i, jtf.getText());
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(320, 120);
        }
    }

    private void display() {
        JFrame f = new JFrame("TabEdit");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TabEdit().display();
            }
        });
    }
}
@trashgod, работая с вашей SSCCE, я смог решить и основную проблему, с которой столкнулся. Вместо использованияfinal String name параметр какoldName вActionListenerЯ вместо этого получаю заголовок вкладки, и она отлично работает. Еще раз спасибо :) A D
@AD: Опять же, я рекомендую вам принять этот ответ и задать второй вопрос в новой ветке. 1+.
@AD: я просто добавил слушатель действия прямо в текстовое поле, чтобы использоватьEnter связывание ключей. Не стесняйтесь приспосабливать это sscce к любому связанному вопросу, идущему вперед.
Спасибо за ответ. Это устранило проблему, которая возникла у меня с заголовком вкладки, но я все еще не могу несколько раз изменить имя сотрудника. A D
Я разработал выше.

Похожие вопросы