0

I am trying to make a GUI for my game I created a while back, and I am running into a slight issue while running it.

I want to have the output print to a JTextField in an extended JPanel. However, when I run it, it comes up with this error:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at Classic.print(Classic.java:509)
    at Classic.play(Classic.java:43)
    at Karma.actionPerformed(Karma.java:134)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2346)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6525)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
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:2750)
at java.awt.Component.dispatchEvent(Component.java:4703)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
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:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
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)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Here is the applicable code:

(I will skip Karma.java:134 since this is just the play button.)

Classic.java

import static javax.swing.SwingUtilities.invokeLater; //This is to show where invokeLater comes from
...
public class Classic extends Game {
    private static JFrame gui;
    private static GUIClassic newContentPane;
    ...
    public void play() {
        invokeLater(Classic::startGUI);
        //The next line is "Classic.java:43
        //length, difficulty, and log are all strings that were initialized when the game was instantiated
        print("Selected Options:\nLength: " + length + "\nDifficulty: " + difficulty + "\nOutput Log? " + log + "\n");
        ...
    }
    private static void startGUI() {
        gui = new JFrame("Karma :: Classic Mode");
        gui.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        newContentPane = new GUIClassic();
        newContentPane.setOpaque(true);
        gui.setContentPane(newContentPane);
        gui.pack();
        gui.setVisible(true);
    }
    private static void print(String text) {
        newContentPane.appendOutput(text);
    }

GUIClassic.java (The class used for the content pane) [EDIT: This is the full class contents for context.]

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GUIClassic extends JPanel implements ActionListener {
    private JTextArea output;
    private JTextField input;
    private boolean inputReady;
    private String inputText;
    public GUIClassic() {
        super();
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        output = new JTextArea(15, 15);
        output.setEditable(false);
        JScrollPane outputScroll = new JScrollPane(output);
        input = new JTextField("",40);
        add(outputScroll);
        add(Box.createRigidArea(new Dimension(0,5)));
        add(input);
    }
    public void actionPerformed(ActionEvent e) {
        inputText = input.getText();
        inputReady = true;
        input.setText("");
    }
    public boolean isInputReady() {
        return inputReady;
    }
    public String getInput() {
        if (!isInputReady())
            return null;
        inputReady = false;
        return inputText;
    }
    public void appendOutput(String addition) {
        output.append(addition + "\n");
    }
}

Interestingly enough, the GUI does pop up and stay up after the exception occurs. It just doesn't print the output to the JTextArea and gets stuck.

If you need more code for context, let me know please and I will add it.

EDIT: Some have pointed out that certain fields may not be initialized. I addressed those accordingly. I tried figuring out exactly what was causing the exception, but failed. It shouldn't be 'newContentPane' or 'output' because those both appear on the screen when the program starts.

greatmastermario
  • 69
  • 1
  • 1
  • 9
  • Looks like `newContentPane` is `null`, you never initialize it. – Tunaki Aug 25 '15 at 17:47
  • possible duplicate of [What is a Null Pointer Exception, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do-i-fix-it) – Tunaki Aug 25 '15 at 17:48
  • Tunaki, I initialized it in the StartGUI method. I also tried moving to the initialization to the very beginning of the class, and the same error occurred. – greatmastermario Aug 25 '15 at 18:17
  • Which line is line 509 of Classic.java? That's where the stacktrace is pointing, and where you should be looking. – Hovercraft Full Of Eels Aug 25 '15 at 19:26
  • It's the instruction line inside the print method. We figured our it's due to the invokeLater call in the line preceding the first print call of play(). Now it's a matter of finding how to implement a Runnable. – greatmastermario Aug 25 '15 at 19:32

2 Answers2

2

You are calling print before your JTextArea has been created. invokeLater is running previous to the print call. Best way to fix (IMO) would be to print your output statement at the end of a Runnable.run method that calls Classic.startGUI first, initiated through invokeLater, instead of the Classic::startGUI constructor by itself

    invokeLater(Classic::startGUI);
    //The next line is "Classic.java:43
    //length, difficulty, and log are all strings that were initialized when the game was instantiated
    print("Selected Options:\nLength: " + length + "\nDifficulty: " + difficulty + "\nOutput Log? " + log + "\n");
ControlAltDel
  • 28,815
  • 6
  • 42
  • 68
  • I just added the full source of the GUIClassic class. The JTextArea is initialized inside the contructor. Also, the invokeLater() method is done as 'import static javax.swing.SwingUtilities.invokeLater;' This is now shown on the cut of the Classic.java source. – greatmastermario Aug 25 '15 at 18:24
  • Listen to what I'm saying: This line in play(): `print("Selected Options:\nLength: " + length + "\nDifficulty: " + difficulty + "\nOutput Log? " + log + "\n");` Happens before this line, in startGUI: `newContentPane = new GUIClassic();` – ControlAltDel Aug 25 '15 at 18:31
  • 1
    @greatmastermario: you're not taking threading into account. All the code in the `invokeLater` is being queued onto the Swing event thread, and so is not being called immediately. This means that you're likely printing before your GUI has been fully created.or rendered. – Hovercraft Full Of Eels Aug 25 '15 at 18:45
  • I see what you're saying now. Is there a way to either delay the next line or invoke 'startGUI' immediately? I tried changing it to just 'startGUI()', but that just brought up the JFrame and nothing else. The code that caused the exception at least brought up components. – greatmastermario Aug 25 '15 at 18:54
1

Check this out, here's your error:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at Classic.print(Classic.java:509)

Here's your Classic#print

private static void print(String text) {
    newContentPane.appendOutput(text);
}

Here, the only scenario that would throw a NullPointerException is when newContentPane equalsnull.

Yes, you might have some code that initializes newContentPane, but its not happening in time before your call to Classic#print.

So, why isn't it happening in time? Like what everyone's been trying to tell you, it has to do with the use of invokeLater.

strider
  • 4,314
  • 2
  • 21
  • 29
  • What would be an acceptable alternative for invokeLater? When I just call startGUI without the invokeLater, it doesn't show the GUI components, whereas the previous code that causes the error ironically does show them. – greatmastermario Aug 25 '15 at 19:10
  • have you tried @ControlAltDel suggestion with `Runnable#run`? – strider Aug 25 '15 at 19:15
  • I will have to try it when I get home. For clarification, would the Runnable contain all the code from play() or just invokeLater(Classic::startGUI)? – greatmastermario Aug 25 '15 at 19:25
  • 1
    just google how `Runnable` works with `invokeLater` and it'll make sense, heres a ref: http://stackoverflow.com/questions/12077245/what-is-swingutilities-invokelater – strider Aug 25 '15 at 19:32