JTabbedPane中的选项卡不会反映按下按钮时的更改 [英] Tab in JTabbedPane does not reflect changes on button press
问题描述
在我的GUI选项卡中,允许用户编辑员工的姓名。该名称也用作选项卡的标签,因此当确认更改时,应更新选项卡以反映此更改,并将新数据写入数据文件。
Within a tab of my GUI, the user is allowed to edit an employee's name. The name also serves as the tab's label, so when the change is confirmed the tab should be updated to reflect this change and the new data is written to a data file.
员工存储在类 Employees
中的 HashMap
中。通过遍历员工姓名的 ArrayList< String>
来填充选项卡,这些名称来自调用方法 Employees.getNames()
。在GUI中,用户可以键入新名称,然后按更改名称按钮。按钮的 ActionListener
调用方法 changeName()
,它将旧名称替换为<$ c中的新名称$ c> HashMap 并更新数据文件。
The employees are stored in a HashMap
in the class Employees
. The tabs are populated by iterating through an ArrayList<String>
of employees' names, which is gotten from calling the method Employees.getNames()
. From the GUI, the user can type in a new name and then press the change name button. The button's ActionListener
calls the method changeName()
, which replaces the old name with the new name in the HashMap
and updates the data file.
这在用户第一次想要更改员工姓名时正常工作,但后续更改会产生错误。看来 JPanel
包含 JTextFields
(参见 getEmployeeInfoPanel()
下面)没有更新参数 name
。此参数是员工的当前名称,而新名称来自 JTextField
。
This works correctly the first time a user wants to change the employee's name, but subsequent changes yield an error. It appears that the JPanel
which contains the JTextFields
(see getEmployeeInfoPanel()
below) is not updating the parameter name
. This parameter is the employee's current name, while the new name is gotten from the JTextField
.
下面举例说明这个问题。基本上,步骤是:
An example to illustrate this problem is below. Essentially, the steps are:
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.
此特定屏幕的层次结构为:
The hierarchy of this particular screen is:
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)
|
-- .....
以下是来自GUI的相关代码:
And here is the relevant code from the 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;
}
}
以下是Employees类中的代码更改HashMap:
and here is the code from the class Employees that changes the 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()
会这样做。
Here is an example. The first screen shot is from when the program is started; the employee names are populated into the appropriate tabs. The second screen shot is after attempting to change the employee's name. As you can see, the tab's label has not changed, which I assumed the call to validate()
would do.
(之前)
(按下按钮后)
最后,按两次更改名称按钮的输出产生,显示名称已被输出在ArrayList中更改:
And finally, the output that pressing the change name button twice produces, showing that the name has been changed in the 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.
推荐答案
您可能正在寻找 setTitleAt()
方法。
You may be looking for the setTitleAt()
method.
附录:为了比较,这里是 sscce 。
Addendum: For comparison, here's an sscce that allows multiple edits.
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();
}
});
}
}
这篇关于JTabbedPane中的选项卡不会反映按下按钮时的更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!