NullPointerException для созданной кнопки в слушателе действий

Следующий код представляет собой фрагмент программы, из которой я получаю исключение nullpointer. Когда я нажимаю кнопку "Добавить" в графическом интерфейсе, появляется сообщение об ошибке, указывающее на эту строку:

  buttonPanel.addButton.setEnabled(false);

отображается. Я предполагаю, что addButton является нулевым по некоторым причинам, хотя я создал его в конструкторе buttonPanel:

 addButton = new JButton("Add");
 addButton.addActionListener(buttonListener);

Почему ошибка нулевого указателя

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at AddButtonListener.actionPerformed(AddButtonListener.java:21)

появляются? Когда слушатель закодирован внутри класса buttonPanel, программа работает без ошибок. Заранее спасибо за помощь!

import java.awt.GridLayout;
import javax.swing.*;

public class ButtonPanel extends JPanel{
    public JButton addButton,
                   editButton,
                   deleteButton,
                   acceptButton,
                   cancelButton,
                   exitButton;

    public JPanel topPanel,
                   exitPanel;

    private ParentFrame parentFrame;

    public static String buttonStatus;

    public ButtonPanel(ParentFrame parent){
        parentFrame = parent;

        buttonStatus = "idle";
        //Create Buttons

        AddButtonListener buttonListener = new AddButtonListener(parent);
        addButton = new JButton("Add");
        addButton.addActionListener(buttonListener);
        editButton = new JButton("Edit");
        deleteButton = new JButton("Delete");
        acceptButton = new JButton("Accept");
        cancelButton = new JButton("Cancel");
        exitButton = new JButton("Exit");

        //Manipulate Buttons
        acceptButton.setEnabled(false);
        cancelButton.setEnabled(false);

        //Add to panels
        topPanel = new JPanel();
        topPanel.add(addButton);
        topPanel.add(editButton);
        topPanel.add(deleteButton);
        topPanel.add(acceptButton);
        topPanel.add(cancelButton);

        exitPanel = new JPanel();
        exitPanel.add(exitButton);

        this.setLayout(new GridLayout(2,1));
        this.add(topPanel);
        this.add(exitPanel);
    }
}

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

public class AddButtonListener implements ActionListener{

    private ParentFrame myFrame;

    private ButtonPanel buttonPanel;

    public AddButtonListener(ParentFrame parent){
        myFrame = parent;
        buttonPanel = parent.buttonPanel;
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        buttonPanel.buttonStatus = "add";

        buttonPanel.addButton.setEnabled(false);
        buttonPanel.editButton.setEnabled(false);
        buttonPanel.deleteButton.setEnabled(false);

        buttonPanel.acceptButton.setEnabled(true);
        buttonPanel.cancelButton.setEnabled(true);
    }

}

import java.awt.BorderLayout;
import javax.swing.JFrame;

public class ParentFrame extends JFrame{

    public ButtonPanel buttonPanel;

    public ParentFrame(){
        this.setResizable(false);

        buttonPanel = new ButtonPanel(this);

        this.add(buttonPanel, BorderLayout.SOUTH);
        this.pack();

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(400, 300);
    }

    public static void main(String[] args){
        ParentFrame frame = new ParentFrame();
        frame.setVisible(true);
    }
}

4 ответа

Решение

Ваша кнопочная панель требует ссылки на ParentFrame быть построенным. ButtonPanel создается в родительском фрейме и создает слушателя, который ссылается на панель кнопок родительского фрейма.

К сожалению, панель кнопок не была назначена в этот момент, и поэтому ваш слушатель действия имеет нулевое значение, назначенное его экземпляру панели кнопок.

Я думаю, проблема в том, что ваш экземпляр панели кнопок в вашем AddButtonListener,

Вы можете исправить это, передав экземпляр ButtonPanel в свой AddButtonListener конструктор. Как AddButtonListener не использует ParentFrame, не беспокойтесь об этом.

private ButtonPanel buttonPanel;
public AddButtonListener(ButtonPanel panel){
    myFrame = parent;
    buttonPanel = panel;
}

И тогда в вашей кнопочной панели конструктор:

public ButtonPanel(ParentFrame parent){
    parentFrame = parent;

    buttonStatus = "idle";
    //Create Buttons

    AddButtonListener buttonListener = new AddButtonListener(this);
    //rest the code

Кроме того, вы не должны структурировать такие вещи. То, что вы делаете, тесно связывает ваши ButtonPanel с вашим ParentFrame, Это означает, что если ваш родительский фрейм изменится, это может вызвать другое изменение ButtonPanel, что делает для менее обслуживаемого кода.

Вы добавляете new AddButtonListener(parent); перед ButtonPanel(ParentFrame parent) полностью инициализирован, поэтому все его компоненты имеют значение null.

Вы могли бы удалить код инициализации, который:

public yourClass()
{
    initComponents();
    btn(false);
}

Сделайте следующее в AddButtonListener

public void actionPerformed(ActionEvent ae) {
    // change all references to buttonPanel to myFrame.buttonPanel
    myFrame.buttonPanel.buttonStatus = "add";
    ...
}

Это потому, что когда вы создаете ButtonPanel, переменная buttonPanel внутри ParentFrame, которую вы передаете, является нулевой в тот самый момент.

увидеть

public ParentFrame(){
    ...
    // when you initialize this, buttonPanel is null until constructing is complete
    buttonPanel = new ButtonPanel(this);
    ...
}

Поэтому AddButtonListener.buttonPanel имеет значение null.

Другие вопросы по тегам