繁体   English   中英

如何使用外部类实现ActionListener?

[英]How to implement ActionListener using an outer class?

当我将ActionListener实现为已注册的侦听器类的内部类时,它可以正常工作,但是当我尝试在已注册的类(即外部类)之外进行操作时,则按钮操作无效。

谁能解释我为什么? 或有任何建议将ActionListener实现为外部类?

代码如下。 提前致谢。

// MainMethod.java

import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class MainMethod
{
  public static void main(String[] args)
  {
    Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
    JFrame frame = new Framework("Tic Tac Toe", size.width / 4,
        size.height / 3, 950, size.height / 8);

    JPanel panel = new ButtonPanel();

    frame.getContentPane().add(panel);
    frame.setVisible(true);
  }
}


// ButtonPanel.java
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;

public class ButtonPanel extends JPanel
{
  private static final long serialVersionUID = -4829885180501818987L;
  JButton buttons[] = new JButton[9];

  ButtonPanel()
  {

    String name[] = { "button1", "button2", "button3", "button4", "button5",
        "button6", "button7", "button8", "button9" };

    Border lineBorder = new LineBorder(Color.black, 2);
    GridLayout panelLayout = new GridLayout(3, 3);
    setLayout(panelLayout);

    for (int i = 0; i < name.length; i++)
    {
      buttons[i] = new JButton(name[i]);
      buttons[i].setBackground(Color.white);
      buttons[i].setBorder(lineBorder);
      buttons[i].addActionListener(new ButtonActionListener());
      add(buttons[i]);
    }
  }

  // Inner class implementation
  class ButtonActionListener implements ActionListener
  {
    public void actionPerformed(ActionEvent ae)
    {

      if (ae.getActionCommand().equals("button1"))
      {
        buttons[0].setText("X");
      }
    }
  }
}

以下是外部类实现,该实现在使用时不起作用:

// ButtonActionListener.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

class ButtonActionListener implements ActionListener
{
  public void actionPerformed(ActionEvent ae)
  {
    ButtonPanel buttonPanel = new ButtonPanel();
    if (ae.getActionCommand() == "button1")
    {
      buttonPanel.buttons[0].setText("X");
    }
  }
}

在您的外部ButtonActionListener类中,编写类似以下内容的内容:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;

public class ButtonActionListener implements ActionListener
{
  public void actionPerformed(ActionEvent event)
  {
    if (event.getActionCommand().equals("button1"))
    {
      ((JButton) (event.getSource())).setText("X");
    }
  }
}

您可以调用getSource()方法来获取调用此actionPerformed(ActionEvent)方法的ButtonActionListener ,然后将其ButtonActionListenerJButton ,因为我们知道它的ButtonActionListener ,然后设置其适当的文本。

更新:

这是如何使用外部ActionListener类的演示:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Demo
{
  public static final String BUTTON_1 = "Demo.BUTTON_1";
  public static final String BUTTON_2 = "Demo.BUTTON_2";

  public Demo()
  {
    JFrame frame = new JFrame("Outer ActionListener");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new FlowLayout(FlowLayout.CENTER));

    ButtonActionListener buttonActionListener = new ButtonActionListener();

    JButton button1 = new JButton("Button 1");
    button1.setActionCommand(Demo.BUTTON_1);
    button1.addActionListener(buttonActionListener);

    JButton button2 = new JButton("Button 2");
    button2.setActionCommand(Demo.BUTTON_2);
    button2.addActionListener(buttonActionListener);

    frame.add(button1);
    frame.add(button2);

    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    frame.setVisible(true);
  }

  public static void main(String[] args)
  {
    // Doing this because Swing is not thread safe.
    SwingUtilities.invokeLater(new Runnable()
    {
      @Override
      public void run()
      {
        new Demo();
      }
    });
  }
}

class ButtonActionListener implements ActionListener
{
  @Override
  public void actionPerformed(ActionEvent event)
  {
    String actionCommand = event.getActionCommand();

    // Since Java 7, String can be used in switch statements
    switch (actionCommand)
    {
      case Demo.BUTTON_1:
        System.out.println("Button 1 is clicked.");
        break;

      case Demo.BUTTON_2:
        System.out.println("Button 2 is clicked.");
        break;

      default:
        System.out.println("I don't know!");
        break;
    }
  }
}

希望您的疑问现在已经清除。

顺便说一句,您还可以使用Anonymous Inner类来添加组件上的侦听器,并且自JDK 8开始,使用Lambda Expressions。 您可以搜索这些事情如何在线完成(如果您想了解实现同一件事的其他方法)。

您正在外部ActionListener中创建一个新的ButtonPanel对象。 这个新的ButtonPanel对象与正在显示并与用户交互的对象完全不同。

一个解决方案:通过侦听器的构造函数将对真正的ButtonPanel实例的引用传递到外部侦听器中。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

class ButtonActionListener implements ActionListener
{
  private ButtonPanel buttonPanel;

  public ButtonActionListener(ButtonPanel buttonPanel)
  {
    this.buttonPanel = buttonPanel;
  }

  public void actionPerformed(ActionEvent actionEvent)
  {
    // ButtonPanel bp=new ButtonPanel();
    if (actionEvent.getActionCommand().equals("button1"))
    {
      buttonPanel.buttons[0].setText("X");
    }
  }
}

然后,您可以通过以下方式进行设置:

buttons[i].addActionListener(
    new ButtonActionListener(/*pass in the valid ButtonPanel reference here*/));

另一个更好的选择是将按钮链接到Model对象,为控件提供对Model对象的引用,并让其对模型进行方法调用或对其模型侦听器进行通知调用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM