JTabbedPane中的选项卡不会反映按下按钮时的更改 [英] Tab in JTabbedPane does not reflect changes on button press

查看:113
本文介绍了JTabbedPane中的选项卡不会反映按下按钮时的更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆