【问题标题】:java.lang.NullPointerException on ActionListener | Java swingActionListener 上的 java.lang.NullPointerException | Java 摇摆
【发布时间】:2014-10-02 17:55:39
【问题描述】:

我确实为创建这个问题提前道歉,我使用 .NET,所以我知道提出这个问题的“感觉”,但我确实搜索并尝试在 Eclipse 中调试我的程序,但仍然无法弄清楚如何修复它,因为我对 Java GUI 完全陌生并且第一次使用 Eclipse,所以...

我有一个小程序Java swing GUI程序,你有2个按钮,其中一个是隐藏的(可见设置为false),当点击一个按钮时,它会显示隐藏按钮(设置Visible为true):

import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

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

public class TestButton extends JPanel {

    private JFrame mainFrame;
    private JButton btnShow ;
    private JButton btnNew;

    public TestButton() {
        mainFrame = new JFrame("Test Button");

        JButton btnShow = new JButton("Show New Button");
        JButton btnNew = new JButton("This is New Button");

        Container c = mainFrame.getContentPane();
        c.setLayout(new FlowLayout());

        c.add(btnShow);
        c.add(btnNew);
        btnNew.setVisible(false);

        btnShow.setMnemonic('G');
        btnNew.setMnemonic('N');

        mainFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });

        ShowButtonHandler ghandler = new ShowButtonHandler();
        btnShow.addActionListener(ghandler);

        mainFrame.setSize(250, 150);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setResizable(false);
        mainFrame.setVisible(true);
    }

    class ShowButtonHandler implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            btnNew.setVisible(true);
        }
    }

    public static void main(String args[]) {
        TestButton app = new TestButton();
    }
}

但是当我点击那个按钮时,它显示 Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException

错误出现在这一行:btnNew.setVisible(true);

这是完整的跟踪:

 Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at TestButton$ShowButtonHandler.actionPerformed(TestButton.java:51)
    at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
    at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
    at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
    at java.awt.Component.processMouseEvent(Unknown Source)
    at javax.swing.JComponent.processMouseEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
    at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Window.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

所以通常当对象未初始化时会发生 Null 异常,但我在声明它时确实初始化了 btnNew,不是吗?问题出在哪里?

另外,我想再添加 1 个名为“再次运行”的按钮,单击它会关闭当前窗口并打开新窗口(基本上我想再次重新运行程序),是否有可能或如何我存档了?

【问题讨论】:

    标签: java swing actionlistener


    【解决方案1】:

    你的局部变量隐藏了实例变量

    改变

    JButton btnNew = new JButton("This is New Button");
    

    btnNew = new JButton("This is New Button");
    

    编辑

    根据您的问题作为评论...但最好提出一个新问题或将您的代码发布到https://codereview.stackexchange.com/

    我的意思是你的内部类ShowButtonHandler依赖于外部类TestButton,因为它使用了外部类的字段btnNew

    class ShowButtonHandler implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            btnNew.setVisible(true);
        }
    }
    

    但是这种依赖不是必需的。 ShowButtonHandler 只需要对 JButton 的引用,它必须在执行操作时设置为可见。

    因此,在第一步中,您可以通过简单地将按钮作为构造函数参数传递来打破对外部类的依赖。

    class ShowButtonHandler implements ActionListener {
    
        private JButton btnNew;
    
        public ShowButtonHandler(JButton btnNew){
            this.btnNew = btnNew;
        }
    
        public void actionPerformed(ActionEvent e) {
            btnNew.setVisible(true);
        }
    }
    

    现在您意识到ShowButtonHandler 可以更灵活地允许重用。查看类层次结构,您会发现setVisible 可以用于任何JComponent。所以你可以让这个类更通用。

    class ShowComponentHandler implements ActionListener {
    
        private JComponent component;
    
        public ShowComponentHandler(JComponent component){
            this.component = component;
        }
    
        public void actionPerformed(ActionEvent e) {
            component.setVisible(true);
        }
    }
    

    由于ShowButtonHandler 现在是独立的并且具有更通用的 API,它可以放置在自己的编译单元(java 文件)中并被重复使用。

    在你的TestButton 类中你仍然可以使用它

    ActionListener showComponentAction = new ShowComponentHandler(btnNew);
    btnShow.addActionListener(showComponentAction);
    

    【讨论】:

    • 完美!非常感谢
    • 让我问你一个简单的问题,我想添加一个名为“再次运行”的按钮,单击它,它会关闭当前窗口并打开新窗口,是否可以这样或如何要我存档吗?
    • 这样是可能的。但我会让处理程序完全独立于TestButton 类。只需将 btnNew 传递给构造函数,例如new ShowButtonHandler(btnNew); 并将其保存在 ShowButtonHandler 的实例变量中
    • 你能更新你的答案吗,我想我明白你的想法,但我是这个 java 语法的新手,所以......?
    • 我更新了我的答案。只需尝试实施和改进您的代码。在这里提出新问题或在codereview.stackexchange.com 上发布您的代码。
    猜你喜欢
    • 2010-12-16
    • 1970-01-01
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-20
    • 2014-04-19
    • 2020-07-03
    相关资源
    最近更新 更多