Action初始化的区别

时间:2015-03-29 20:58:58

标签: java swing event-handling action

我试图创建程序,其中Action类是一个类的内部类,但是它的对象的初始化发生在另一个类中,但是我总是得到一个异常。下面我介绍我的问题的简化模型:

有一个类构建GUI并包含Action的内部类:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

public class SomeClass {
    JTextArea area;
    public static void main(String[] args){
        SomeClass outerAction = new SomeClass();
        outerAction.go();
    }
    public void go(){
    JFrame frame = new JFrame();
    area = new JTextArea(5,10);
    JToolBar toolBar = new JToolBar(SwingConstants.HORIZONTAL);
    CreateAction createAction = new CreateAction();
    JButton button1 = new JButton(innerGetAction());
    JButton button2 = new JButton(createAction.otherGetAction());
    toolBar.add(button1);
    toolBar.add(button2);

    frame.getContentPane().add(BorderLayout.PAGE_START,toolBar);
    frame.getContentPane().add(BorderLayout.CENTER,area);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
}
public Action innerGetAction(){
    Action action = new SomeAction("DO","Do sth",KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
    return action;
}
    public class SomeAction extends AbstractAction{
        public SomeAction(String name, String desc, KeyStroke key){
            super(name);
            putValue(SHORT_DESCRIPTION,desc);
            putValue(ACCELERATOR_KEY,key);
        }
        public void actionPerformed(ActionEvent e) {
            area.setText("Done");
        }
    }
}

有两个JButton具有相同的Action,但是初始化首先出现在SomeClass中,另一个出现在单独的CreateActionClass中:

import javax.swing.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

public class CreateAction {
    public static Action otherGetAction(){
        Action action = new SomeClass().new SomeAction("DO","Do sth",KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
        return action;
    }
}

一个按钮工作正常,另一个按钮异常。我不明白为什么。

你可以告诉我:

  1. 为什么在类CreateAction中初始化的Action没有从SomeClass访问字段? 如果getAction是SomeClass的方法,一切都可以,它可以修改JTextArea,但是当它是CreateAction的方法时,会有一个java.lang.NullPointerException。有什么区别?
  2. 初始化Action对象在不同的​​类中是否有意义,而不是它的Action类和构造函数?
  3. 原谅我可怜的榜样。

    堆栈跟踪:

      

    线程“AWT-EventQueue-0”中的异常java.lang.NullPointerException       在SomeClass $ SomeAction.actionPerformed(SomeClass.java:40)       在javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)       在javax.swing.AbstractButton $ Handler.actionPerformed(AbstractButton.java:2346)       在javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)       在javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)       在javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)       在java.awt.AWTEventMulticaster.mouseReleased(AWTEventMulticaster.java:289)       at java.awt.Component.processMouseEvent(Component.java:6525)       在javax.swing.JComponent.processMouseEvent(JComponent.java:3321)       at java.awt.Component.processEvent(Component.java:6290)       at java.awt.Container.processEvent(Container.java:2234)       at java.awt.Component.dispatchEventImpl(Component.java:4881)       at java.awt.Container.dispatchEventImpl(Container.java:2292)       at java.awt.Component.dispatchEvent(Component.java:4703)       at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4898)       at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4533)       at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4462)       at java.awt.Container.dispatchEventImpl(Container.java:2278)       at java.awt.Window.dispatchEventImpl(Window.java:2739)       at java.awt.Component.dispatchEvent(Component.java:4703)       at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)       at java.awt.EventQueue.access $ 400(EventQueue.java:97)       at java.awt.EventQueue $ 3.run(EventQueue.java:697)       at java.awt.EventQueue $ 3.run(EventQueue.java:691)       at java.security.AccessController.doPrivileged(Native Method)       at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:75)       at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:86)       at java.awt.EventQueue $ 4.run(EventQueue.java:719)       at java.awt.EventQueue $ 4.run(EventQueue.java:717)       at java.security.AccessController.doPrivileged(Native Method)       at java.security.ProtectionDomain $ 1.doIntersectionPrivilege(ProtectionDomain.java:75)       在java.awt.EventQueue.dispatchEvent(EventQueue.java:716)       at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)       at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)       at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)       在java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

1 个答案:

答案 0 :(得分:4)

您正在获取NullPointerException,因为您正在使用错误的SomeClass在此处创建操作:

Action action = new SomeClass().new SomeAction("DO", "Do sth",
        KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));

new SomeClass()不是显示的SomeClass!

相反,请考虑传入可视化对象。

public static Action otherGetAction(SomeClass someClass) {
  return someClass.new SomeAction("DO", "Do sth",
        KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_MASK));
}

如果您要将GUI设置在GUI之外,请考虑将Action分离出GUI。例如:

import java.awt.event.ActionEvent;
import javax.swing.*;

public class Test2 extends JPanel implements Fooable {
   private JTextField field = new JTextField(10);
   private JTextArea textarea = new JTextArea(20, 30);
   private JButton button = new JButton();

   public Test2() {
      textarea.setFocusable(false);
      JScrollPane scrollPane = new JScrollPane(textarea);
      scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

      add(field);
      add(scrollPane);

      add(button);
   }

   public void setActions(Action action) {
      button.setAction(action);
      field.setAction(action);
   }

   @Override
   public String getFieldText() {
      field.selectAll();
      return field.getText();
   }

   @Override
   public void appendText(String text) {
      textarea.append(text + "\n");
   }


   private static void createAndShowGui() {
      Test2 mainPanel = new Test2();
      Action myAction = new MyAction("Press Me", KeyEvent.VK_P, mainPanel);
      mainPanel.setActions(myAction);

      JFrame frame = new JFrame("Test2");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }

}

interface Fooable {
   String getFieldText();
   void appendText(String text);
}

class MyAction extends AbstractAction {
   private Fooable fooable;

   public MyAction(String name, int mnemonic, Fooable fooable) {
      super(name);
      putValue(MNEMONIC_KEY, mnemonic);
      this.fooable = fooable;
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      if (fooable != null) {
         fooable.appendText(fooable.getFieldText());
      }
   }
}