【问题标题】:How can I access an Array List's elements inside an ActionListener from another ActionListener?如何从另一个 ActionListener 访问 ActionListener 内的 Array List 的元素?
【发布时间】:2014-04-28 04:05:48
【问题描述】:

我在一个主类中有两个 Action Listener 内部类。每一个都对应自己的按钮。其中一个动作侦听器被编码为生成一个数组列表。另一个只是将该数组列表写入文本字段。

我的问题是如何从其他 Action Listener 引用/访问该数据?下面的代码可以编译,但是当我从第二个 Action Listener 检查 Array List 的内容时,它是空的 ([])。

我猜这与调用其他动作侦听器的 actionPerformed 方法时重新实例化的数组列表有关。我该如何解决这个问题? (这里的代码只是 2 个动作监听器)。


// Create a Button Listener Inner Class for Input Route Button.
class InputRouteButtonHandler implements ActionListener {

    List<String> routeStopList = new ArrayList<String>();

    public void actionPerformed(ActionEvent event) {

        String city1 = (String) cityCombo1.getSelectedItem();
        String city2 = (String) cityCombo2.getSelectedItem();

        if (city1.equals(city2)) {
            JOptionPane.showMessageDialog(null, "Invalid route chosen. Please choose two different cities.");
        } else {
            routeStopList.add(city1); //Add city1 to start of array.
            int dialogResult;

            do {
                String routeStop = JOptionPane.showInputDialog("Enter a stop between the 2 cities:");
                routeStopList.add(routeStop);
                dialogResult = JOptionPane.showConfirmDialog(null, "Add another stop?");
            } while (dialogResult.equals(JOptionPane.YES_OPTION));

            routeStopList.add(city2); //Add city2 to end of array.
            System.out.println(routeStopList); //Just checking ArrayList contents
        }
    }
}

// Create a Button Listener Inner Class for Route Button.
class RouteButtonHandler extends InputRouteButtonHandler implements ActionListener {

    public void actionPerformed(ActionEvent event) {

        String city1 = (String) cityCombo1.getSelectedItem();
        String city2 = (String) cityCombo2.getSelectedItem();

        System.out.println(routeStopList); //Just checking ArrayList contents

        if (city1.equals(city2)) {
            JOptionPane.showMessageDialog(null, "Invalid route chosen. Please choose two different cities.");
        } else {
            for (int i = 0; i < routeStopList.size(); i++) {
                String addedRoute = routeStopList.get(i);
                adminPanelTextArea.append(addedRoute + "\n");
            }
        }
    }
}

【问题讨论】:

    标签: java swing arraylist


    【解决方案1】:

    您是对的,您的问题是由于您创建了两个 ArrayList,这些列表彼此之间绝对没有关系,除了持有相同类型的对象并具有相同的名称。一种解决方案是创建一个由两个 ActionListener 类共享的模型类,并在此模型类中拥有您的 ArrayList。然后为您的 ArrayList 类提供一个 setModel(Model model) 方法或构造函数,并将对单个 Model 对象的引用传递给两个 ActionListener。


    另一个考虑因素是使用单个 Control 类来处理您的侦听器类型代码,然后让您的 Control 类保存一个 Model 字段。


    顺便说一句,这是危险的代码:

    if (city1 == city2) {
    

    不要使用== 比较字符串。请改用equals(...)equalsIgnoreCase(...) 方法。了解== 检查两个 objects 是否相同,这不是您感兴趣的。另一方面,这些方法检查两个字符串是否以相同的顺序具有相同的字符,这就是这里重要的事情。


    例如,假设您有两个想要操作 JList 的按钮,一个想要添加文本,另一个想要清除它,那么您可以将 JList 的模型传递给两个按钮处理程序。示例程序可能如下所示:

    import java.awt.BorderLayout;
    import java.awt.event.*;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class ShareList extends JPanel {
       private static final String PROTOTYPE_CELL_VALUE = "ABCDEFGHIJKLMNOP";
       private static final int VISIBLE_ROW_COUNT = 10;
       private JTextField textField = new JTextField(10);
       private DefaultListModel<String> listModel = new DefaultListModel<>();
       private JList<String> myList = new JList<>(listModel);
    
       public ShareList() {
          myList.setPrototypeCellValue(PROTOTYPE_CELL_VALUE);
          myList.setVisibleRowCount(VISIBLE_ROW_COUNT);
          myList.setFocusable(false);
    
          JPanel buttonPanel = new JPanel();
          AddHandler addHandler = new AddHandler(listModel, this);
          textField.addActionListener(addHandler);
          buttonPanel.add(new JButton(addHandler));
          buttonPanel.add(new JButton(new ClearHandler(listModel)));
    
          JPanel rightPanel = new JPanel(new BorderLayout());
          rightPanel.add(textField, BorderLayout.NORTH);
          rightPanel.add(buttonPanel, BorderLayout.CENTER);
    
          setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
          add(new JScrollPane(myList));
          add(rightPanel);
       }
    
       public String getText() {
          textField.selectAll();
          return textField.getText();
       }
    
       private static void createAndShowGui() {
          JFrame frame = new JFrame("ShareList");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(new ShareList());
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    
    }
    
    @SuppressWarnings("serial")
    class AddHandler extends AbstractAction {
       private DefaultListModel<String> listModel;
       private ShareList shareList;
    
       public AddHandler(DefaultListModel<String> listModel, ShareList shareList) {
          super("Add");
          putValue(MNEMONIC_KEY, KeyEvent.VK_A);
          this.listModel = listModel;
          this.shareList = shareList;
       }
    
       public void actionPerformed(ActionEvent e) {
          String text = shareList.getText();
          listModel.addElement(text);
       };
    }
    
    @SuppressWarnings("serial")
    class ClearHandler extends AbstractAction {
       private DefaultListModel<String> listModel;
    
       public ClearHandler(DefaultListModel<String> listModel) {
          super("Clear");
          putValue(MNEMONIC_KEY, KeyEvent.VK_C);
          this.listModel = listModel;
       }
    
       public void actionPerformed(ActionEvent e) {
          listModel.clear();
       };
    }
    

    【讨论】:

    • 所以我必须创建一个模型类,它由两个动作侦听器扩展,其中包含:List&lt;String&gt; routeStopList = new ArrayList&lt;String&gt;();。然后我需要该模型类中的方法/构造函数,通过该方法/构造函数将来自动作侦听器的字符串附加到数组列表中。
    • @gsymeoni:不,模型从不实现 ActionListener。这就是控制的工作。有关详细信息,请阅读 MVC(模型-视图-控制)设计模式。
    • @gsymeoni:模型将再次保存您的 ArrayList,并且您的控件或者如果您希望您的两个 ActionListener 实现类将保存对同一个模型的引用。这样,一个类中模型的更改将反映在另一个类中。
    • @gsymeoni:或者,您的 ArrayList 可以是这个简单程序中的模型,在这种情况下,您所要做的就是将相同数组列表的引用传递给每个 ActionListener。同样,通过构造函数参数或 setter 方法将其传入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    • 1970-01-01
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    相关资源
    最近更新 更多