【问题标题】:How can I use listeners to access other elements?如何使用侦听器访问其他元素?
【发布时间】:2009-05-03 02:57:31
【问题描述】:

我正在设置一个 GUI,我需要在其中获取从表单元素输入的信息并操作这些信息。这需要我使用一些元素来访问其他元素。

例如,我有一个输入框(JTextField),旁边有一个按钮(JButton)。当按下按钮时,我需要能够操作输入到输入框中的文本。到目前为止,我为完成这项工作所做的一切努力都失败了。

这就是我的代码现在的样子(我已将我的问题嵌入到 cmets 中):

public class MyClass
{
    public static void main(String args[])
    {
        // Form elements are in here
        JTextField myTextField = new JTextField(10);
        JButton myTextFieldSubmit = new JButton("Submit");
        myTextFieldSubmit.addActionListener(new ListenerClass());
    }
}

class ListenerClass implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        // This is what happens when these elements are used
        // I need to be able to access the form elements from MyClass in here, but this doesn't seem possible with my current setup
        // For example, when the Submit button is pressed, I need to be able to myTextField.getText() and edit MyClass members
        // How should my setup be changed to accommodate these needs?
    }
}

感谢您的帮助!

【问题讨论】:

    标签: java user-interface listeners


    【解决方案1】:

    这在很大程度上是一个变量范围问题。

    目前,文本字段和按钮在 main 方法的范围内,因此为 ActionListener 提供一个单独的类将意味着它无法访问这些变量。

    有几种方法可以实现这一点:

    (1)在MyClass中创建一个内部类ListenerClass,并将myTextFieldmyTextFieldSubmit变成MyClass的实例字段。

    public class MyClass
    {
      final static JTextField myTextField = new JTextField(10);
      final static JButton myTextFieldSubmit = new JButton("Submit");
    
      public static void main(String args[])
      {
        myTextFieldSubmit.addActionListener(new ListenerClass());
      }
    
      static class ListenerClass implements ActionListener
      {
        public void actionPerformed(ActionEvent e)
        {
          myTextField.setText("");
        }
      }
    }
    

    (2) 在main 方法中创建一个匿名内部类,这将允许myTextFieldmyTextFieldSubmit 保持在同一个位置,只要它们被声明为final

    public class MyClass
    {
      public static void main(String args[])
      {
        final JTextField myTextField = new JTextField(10);
        final JButton myTextFieldSubmit = new JButton("Submit");
    
        myTextFieldSubmit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
                myTextField.setText("");
            }
        });
      }
    }
    

    (3) 创建一个本地类,该类是main 方法的本地类。同样,这将要求将文本字段和按钮声明为 final 以允许从内部类进行访问。

    public class MyClass
    {
      public static void main(String args[])
      {
        final JTextField myTextField = new JTextField(10);
        final JButton myTextFieldSubmit = new JButton("Submit");
    
        class ListenerClass implements ActionListener
        {
          public void actionPerformed(ActionEvent e)
          {
            myTextField.setText("");
          }
        }
    
        myTextFieldSubmit.addActionListener(new ListenerClass());
      }
    }
    

    (4) 处理对ListenerClass 的引用,例如在构造函数中,同时使myTextFieldmyTextFieldSubmit 成为实例变量。

    public class MyClass
    {
      JTextField myTextField = new JTextField(10);
      JButton myTextFieldSubmit = new JButton("Submit");
    
      public MyClass()
      {
        myTextFieldSubmit.addActionListener(new ListenerClass(this));
      }
    
      public static void main(String args[])
      {
        new MyClass();
      }
    }
    
    class ListenerClass implements ActionListener
    {
      MyClass myClass;
    
      public ListenerClass(MyClass myClass)
      {
        this.myClass = myClass;
      }
    
      public void actionPerformed(ActionEvent e)
      {
        myClass.myTextField.setText("");
      }
    }
    

    (5) 将myTextFieldmyTextFieldSubmit 设为static 字段,并允许从ListerClass 直接访问。

    public class MyClass
    {
      static JTextField myTextField = new JTextField(10);
      static JButton myTextFieldSubmit = new JButton("Submit");
    
      public static void main(String args[])
      {
        myTextFieldSubmit.addActionListener(new ListenerClass());
      }
    }
    
    class ListenerClass implements ActionListener
    {
      public void actionPerformed(ActionEvent e)
      {
        MyClass.myTextField.setText("");
      }
    }
    

    可能还有更多方法可以实现这一点,并且可能有更好的方法来实现这一点。选择哪种方法实际上取决于所需的应用程序设计。

    【讨论】:

    • 谢谢!我将使用(2),因为我认为这是最简洁的方式(至少对我而言)。 :)
    • 我也喜欢 (2),而且我发现只要没有多个实例执行相同的操作,它就可以正常工作。但我应该指出,匿名类可能有缺点,因为它不能从其他类或方法访问。 (尽管在某些情况下这可能是积极的,例如隐藏实现细节。)
    【解决方案2】:

    您可以将构造函数中对MyClass 的引用传递给ListenerClass

    【讨论】:

      【解决方案3】:

      您的问题对于在 Java 中出于任何目的使用侦听器都很常见:如何让处理程序访问通知侦听器或其对等方的对象。

      一般有两种约定。

      一种是直接从事件对象中获取对象。你可以用 getSource() 来做到这一点。但是,您只会得到执行此操作的小部件。

      另一个选项是让侦听器类能够访问小部件。一种方法是使用非静态内部类(这取决于您如何声明它),在这种情况下,它可以访问包含类的成员。

      但是,在这种情况下,您的小部件是变量,而不是成员(您确定要这样做吗?)。因此,您唯一的解决方案是让成员将它们保存在 Listner 类中,然后在 addListener 调用中创建侦听器,而不是创建侦听器,传递相关的小部件,然后添加侦听器。侦听器现在可以通过他自己对存储在成员中的引用访问这些小部件。

      【讨论】:

        猜你喜欢
        • 2013-08-11
        • 2017-04-27
        • 2014-08-27
        • 1970-01-01
        • 2022-09-27
        • 2017-08-28
        • 1970-01-01
        • 2018-01-21
        • 2012-04-25
        相关资源
        最近更新 更多