从另一个类调用方法时发生NullPointerException

时间:2018-10-19 16:55:06

标签: java swing oop nullpointerexception awt

我在制作基于文本的游戏时遇到问题。我对Java和在Java中绘制GUI相当陌生,因此我怀疑我的整体结构可能是问题的根源。所以忍受我吧

我的主类,实例化一个新的Gamelobby()。

class untitledRPG {

public static void main(String[] args) { new GameLobby(); }
}

GameLobby实例化MainMenu()。

class GameLobby {

    {
    mainMenu = new MainMenu();
    }
}

MainMenu()如下所示,如果玩家选择“ New Game”(新游戏)按钮以及Intro()(该游戏文字将来自此),则将GameWindow()设置为空。

public class MainMenu {    

    private String newGame;
    private String loadGame;
    private String settings;
    private JFrame frame = new JFrame("UntitledRPG™ Main Menu");

    public MainMenu() {
        newGame = "New Game";
        loadGame = "Load Game";
        settings = "Settings";
        buildWindow(frame);
    }

    private void buildWindow(JFrame frame)
    {
        // Main build
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setSize(400, 220);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);

        // Draw layout with grid
        // Look into GridBagLayout if this proves insufficient
        frame.setLayout(new GridLayout(3,1));
        JPanel field1 = new JPanel();
        JPanel field2 = new JPanel(new GridLayout(1, 3));
        JPanel field21 = new JPanel();
        JPanel field22 = new JPanel();
        JPanel field23 = new JPanel();
        field2.add(field21);
        field2.add(field22);
        field2.add(field23);
        JPanel field3 = new JPanel();

        // Instantiate objects
        JLabel welcomeTextLabel = new JLabel();
        JLabel gameDescLabel = new JLabel();
        JButton newGameBtn = selectGameTypeBtn(newGame);
        JButton loadGameBtn = selectGameTypeBtn(loadGame);
        JButton settingsBtn = selectGameTypeBtn(settings);

        // Set values. Can be integrated to the instantiation 
        String welcomeText = "Welcome to the Untitled RPG!";
        String gameDesc = "<html>Press 'New Game' to start your adventure,<br /> or 'Load Game' to continue an existing one!</html> ";
        settingsBtn.setText("Settings");
        welcomeTextLabel.setText(welcomeText);
        gameDescLabel.setText(gameDesc);

        //Add objects to panels
        field1.add(welcomeTextLabel);
        field21.add(newGameBtn);
        field22.add(loadGameBtn);
        field23.add(settingsBtn);
        field3.add(gameDescLabel);

        // Add panels to grid
        frame.add(field1);
        frame.add(field2);
        frame.add(field3);

        frame.setVisible(true);
    }

    private JButton selectGameTypeBtn(String btnName) {
        JButton returned = new JButton(btnName);
        returned.addActionListener(e -> {
            JButton source = (JButton)e.getSource();
            if (source.getText().equalsIgnoreCase(newGame)) {
                new GameWindow().openGameWindow();
                new Intro();
                frame.dispose();
            }
            if (source.getText().equalsIgnoreCase(loadGame)) {
                popUp popUp = new popUp();
                popUp.popUpWindow("You have no saves to load!", "Error!");

            }
            if (source.getText().equalsIgnoreCase(settings)) {
                popUp popUp = new popUp();
                popUp.popUpWindow("We haven'made any settings yet!", "Error!");
            }
        });
        return returned;
    }
}

GameWindow()看起来像这样:

public class GameWindow {

private JTextArea sideBarArea;
private JTextArea gameArea;
private JTextArea inputAreaTextArea;
private JTextField inputAreaTextField;
private GridBagConstraints c;

 public GameWindow() {
    c = new GridBagConstraints();
    c.anchor = GridBagConstraints.FIRST_LINE_START;
    int hGap = 5;
    int vGap = 5;
    c.insets = new Insets(hGap, vGap, hGap, vGap);
}

public void openGameWindow() {
    JFrame frame = new JFrame("UntitledRPG™");
    buildGameWindow(frame);
}

private void buildGameWindow(JFrame frame) {

    /* GameWindow build info
    GameWindow consists of:
    - gameArea, a JTextField where the output from the game will be printed.
    - sideBarArea, TODO
    - inputArea, a JPanel where the player enters commands and views them in a log
     */

    // Main build
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setSize(700, 600);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    frame.setVisible(true);

    // Set areas
    gameArea = new JTextArea(5, 10);
    sideBarArea = new JTextArea(5, 10);
    JPanel inputArea = new JPanel(new GridBagLayout());

    // GAME AREA
    gameArea.setEditable(false);
    gameArea.setCaretPosition(gameArea.getDocument().getLength());
    JScrollPane gameAreaScrollPane = new JScrollPane(gameArea);

    //SIDEBAR AREA
    sideBarArea.setEditable(false);

    // INPUT AREA.
    // Set textArea and add it to scrollpane, which is then added to the layout
    inputAreaTextArea = new JTextArea(10,20);
    inputAreaTextArea.setEditable(false);
    inputAreaTextArea.setCaretPosition(inputAreaTextArea.getDocument().getLength());

    // Message in the inputAreaTextArea to user.
    String welcomeMsg= "This is your command log. Your commands will be printed here.";
    printToLog(welcomeMsg);
    JScrollPane textAreaScrollPane = new JScrollPane(inputAreaTextArea);

    // (addComp) method for placing elements in gridBagLayout.
    addComp(inputArea, textAreaScrollPane, 0, 1, 1, 1, GridBagConstraints.BOTH, 2, 2);

    // Label with user instruction on using the inputAreaTextField
    JLabel inputAreaLabel = new JLabel("Enter commands below.");
    addComp(inputArea, inputAreaLabel, 0,2, 1, 1, GridBagConstraints.BOTH, 0.2,0.2);

    // Set jTextfield and add it to layout
    inputAreaTextField = new JTextField();
    inputAreaTextField.setText("Start your adventure!"); // Placeholder, see method below
    addComp(inputArea, inputAreaTextField, 0, 3, 2, 2, GridBagConstraints.BOTH, 0.2, 0.2);

    // Listener for enter-click
    inputAreaTextField.addActionListener((e -> {
        if(inputAreaTextField.getText().length() > 0) {
            printToLog(inputAreaTextField.getText());
            inputAreaTextField.setText("");
        }
    }));

    // Method for the placeholder text. Show up one time before textField is in focus
    inputAreaTextField.addFocusListener(new FocusAdapter() {
        public void focusGained(FocusEvent e) {
            JTextField source = (JTextField)e.getComponent();
            source.setText("");
            source.removeFocusListener(this);
        }
    });

    // ASSEMBLY
    // Set vertical splitpane. Second layer
    JSplitPane vertSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, gameArea, sideBarArea);
    vertSplitPane.setDividerLocation(500);
    vertSplitPane.setDividerSize(10);
    vertSplitPane.setEnabled(false);

    // Set horizontal split. Top layer
    JSplitPane horiSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, vertSplitPane, inputArea);
    vertSplitPane.setOneTouchExpandable(false);
    horiSplitPane.setDividerLocation(400);
    horiSplitPane.setDividerSize(5);
    horiSplitPane.setEnabled(false);

    frame.add(horiSplitPane);
}

// Easier implementation of constraints for gridBagLayout
private void addComp(JPanel panel, JComponent comp
                        , int x, int y, int gWidth
                            , int gHeight, int fill
                                , double weightx, double weighty) {
    c.gridx = x;
    c.gridy = y;
    c.gridwidth = gWidth;
    c.gridheight = gHeight;
    c.fill = fill;
    c.weightx = weightx;
    c.weighty = weighty;

    panel.add(comp, c);
}

// Prints  player command to inputAreaTextField (log)
public void printToLog(String text) {
    inputAreaTextArea.append(">" + text + "\n");
    inputAreaTextArea.setCaretPosition(inputAreaTextArea.getDocument().getLength());
}

public void printToGameArea(String text) {
     gameArea.append(">" + text + "\n");
     gameArea.setCaretPosition(gameArea.getDocument().getLength());
}
}

Intro()看起来像这样:

public class Intro {

Print print;
Player player;


public Intro()
{
    player = new Player();
    print = new Print();
    player = charCreation();
}

private Player charCreation() {
    GameWindow gameWindow = new GameWindow();
    gameWindow.printToGameArea("Wake up");
    player.setAge(21);
    player.setName("Kris");
    player.setGender("m");
    return player;
}
}

但是当我运行它时,我得到这个nullPointerException:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at GUI.GameWindow.printToGameArea(GameWindow.java:138)
at Gameplay.Intro.charCreation(Intro.java:21)
at Gameplay.Intro.<init>(Intro.java:16)
at GUI.MainMenu.lambda$selectGameTypeBtn$0(MainMenu.java:78)

我无法解决造成这种情况的原因,以及如何改善整体结构。

提前感谢您的帮助,如果我的问题不符合SO标准,请告诉我。我也是这个新手。

1 个答案:

答案 0 :(得分:0)

在调用printToGameArea初始化组件之前,您需要调用openGameWindow并最终调用buildGameWindow。

private Player charCreation() {
    GameWindow gameWindow = new GameWindow();
    gameWindow.openGameWindow();
    gameWindow.printToGameArea("Wake up");
    player.setAge(21);
    player.setName("Kris");
    player.setGender("m");
    return player;
}