Вкладка в JTabbedPane не отражает изменения при нажатии кнопки
На вкладке моего графического интерфейса пользователю разрешено редактировать имя сотрудника. Имя также служит меткой вкладки, поэтому, когда изменение подтверждается, вкладка должна быть обновлена, чтобы отразить это изменение, и новые данные записываются в файл данных.
Сотрудники хранятся в HashMap
в классе Employees
, Вкладки заполняются путем итерации ArrayList<String>
имен сотрудников, получаемых при вызове метода 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()
сделал бы.
(До)
(После нажатия кнопки)
И, наконец, вывод, который дважды происходит при нажатии кнопки изменения имени, показывает, что имя было изменено в 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.
1 ответ
Вы можете искать setTitleAt()
метод.
Приложение: для сравнения, вот sscce, который позволяет несколько изменений.
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://stackru.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();
}
});
}
}