Search code examples
javajtextpaneundoundo-redo

java.lang.NullPointerException when trying to add undos to JTextPane


I used this website to try to add undos and redos to my JTextPane, but I get this error:
Exception in thread "main" java.lang.NullPointerException at guiWithSwing.TextEditor.main(TextEditor.java:137).
At line 137, it says menuEdit.add(menuItemUndo);, which is the part that adds the "Undo" button to the menu. I think the error means that the button has no properties, or something is missing, but I don't know what it is, as it has an action and text.

package guiWithSwing;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.StyledDocument;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

@SuppressWarnings("serial")
public class TextEditor extends JPanel {

static Container pane;
static Container paneText;
static BasicFrame frame;
static JTextPane textArea;
static JScrollPane areaScrollPane;
static FileFilter textFile;
static FileFilter htmlFile;
static FileFilter javaFile;
static JLabel label1;
static {
    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }
}
static JFileChooser save = new JFileChooser();
static JFileChooser open = new JFileChooser();
static JMenuBar menuBar;
static JMenu menuFile, menuEdit;
static JMenuItem menuItemNew, menuItemSave, menuItemOpen;
static JMenuItem menuItemUndo, menuItemRedo;
static UndoManager undoManager;
static String newLine = "\n";
static Document editorPaneDocument;
static UndoHandler undoHandler;
static UndoAction undoAction;
static RedoAction redoAction;

public static void main(String[] args) throws ClassNotFoundException,
        InstantiationException, IllegalAccessException,
        UnsupportedLookAndFeelException, IOException {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    frame = BasicFrame.getInstance();
    pane = frame.getContentPane();
    paneText = new JPanel();
    textArea = new JTextPane();
    label1 = new JLabel("          ");
    menuBar = new JMenuBar();
    menuFile = new JMenu("File");
    undoManager = new UndoManager();
    menuFile.setMnemonic(KeyEvent.VK_F);
    menuFile.getAccessibleContext().setAccessibleDescription("File");
    menuBar.add(menuFile);
    menuItemNew = new JMenuItem(
            "New",
            new ImageIcon("Images/new.png"));
    menuItemNew.setMnemonic(KeyEvent.VK_N);
    menuFile.add(menuItemNew);
    menuItemOpen = new JMenuItem(
            "Open",
            new ImageIcon("Images/folder.png"));
    menuItemOpen.setMnemonic(KeyEvent.VK_O);
    menuFile.add(menuItemOpen);
    menuItemSave = new JMenuItem(
            "Save",
            new ImageIcon("Images/save.png"));
    menuItemSave.setMnemonic(KeyEvent.VK_S);
    menuFile.add(menuItemSave);
    areaScrollPane = new JScrollPane(textArea);
    areaScrollPane
            .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    areaScrollPane.setPreferredSize(new Dimension(250, 250));
    pane.setLayout(new BorderLayout());
    textFile = new FileNameExtensionFilter("Text File (.txt)", "txt");
    htmlFile = new FileNameExtensionFilter(
            "HTML Document (.html, .htm, .shtml, .shtm, .xhtml, .hta)",
            "html", "htm", "shtml", "shtm", "xhtml", "hta");
    javaFile = new FileNameExtensionFilter("Java Source Code (.java)",
            "java");
    save.addChoosableFileFilter(textFile);
    save.addChoosableFileFilter(htmlFile);
    save.addChoosableFileFilter(javaFile);
    save.setAcceptAllFileFilterUsed(true);
    save.setFileFilter(textFile);
    open.addChoosableFileFilter(textFile);
    open.addChoosableFileFilter(htmlFile);
    open.addChoosableFileFilter(javaFile);
    open.setAcceptAllFileFilterUsed(true);
    open.setFileFilter(textFile);
    menuItemUndo = new JMenuItem(undoAction);
    menuItemRedo = new JMenuItem(redoAction);
    menuEdit.add(menuItemUndo);
    menuEdit.add(menuItemRedo);
    pane.add(areaScrollPane, BorderLayout.CENTER);
    pane.add(paneText, BorderLayout.SOUTH);
    paneText.setLayout(new BoxLayout(paneText, BoxLayout.Y_AXIS));
    paneText.add(label1);
    editorPaneDocument = textArea.getDocument();
    editorPaneDocument.addUndoableEditListener(undoHandler);
    KeyStroke undoKeystroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
            Event.META_MASK);
    KeyStroke redoKeystroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y,
            Event.META_MASK);
    undoAction = new UndoAction();
    textArea.getInputMap().put(undoKeystroke, "undoKeystroke");
    textArea.getActionMap().put("undoKeystroke", undoAction);
    redoAction = new RedoAction();
    textArea.getInputMap().put(redoKeystroke, "redoKeystroke");
    textArea.getActionMap().put("redoKeystroke", redoAction);

    menuItemNew.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            textArea.setText(null);
        }

    });

    menuItemSave.addActionListener(new ActionListener() {

        public void actionPerformed(ActionEvent e) {
            save.setFileHidingEnabled(false);
            save.setSelectedFile(new File("new 1"));
            save.setMultiSelectionEnabled(true);
            save.setCurrentDirectory(new File(System
                    .getProperty("user.home") + "/Desktop"));
            save.setDialogTitle("Where Would You Like to Save This File?");
            save.setDragEnabled(true);
            int actionDialog = save.showSaveDialog(null);
            if (actionDialog != JFileChooser.APPROVE_OPTION) {
                return;
            } else {
                log("Done!", true);
                String name = save.getSelectedFile().getAbsolutePath();
                if (!name.endsWith(".txt")
                        && save.getFileFilter() == textFile) {
                    name += ".txt";
                } else if (!name.endsWith(".java")
                        && save.getFileFilter() == javaFile) {
                    name += ".java";
                } else if ((!name.endsWith(".html") && save.getFileFilter() == htmlFile)
                        || (!name.endsWith(".htm") && save.getFileFilter() == htmlFile)
                        || (!name.endsWith(".shtml") && save
                                .getFileFilter() == htmlFile)
                        || (!name.endsWith(".shtm") && save.getFileFilter() == htmlFile)
                        || (!name.endsWith(".xhtml") && save
                                .getFileFilter() == htmlFile)
                        || (!name.endsWith(".hta") && save.getFileFilter() == htmlFile)) {
                    name += ".html";
                }
                BufferedWriter outFile = null;
                try {
                    outFile = new BufferedWriter(new FileWriter(name));
                    textArea.write(outFile);

                } catch (IOException ioe) {
                    ioe.printStackTrace();
                } finally {
                    if (outFile != null) {
                        try {
                            outFile.close();
                        } catch (IOException ioee) {
                        }
                    }
                }
            }

        }
    });

    menuItemOpen.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            open.setFileHidingEnabled(false);
            open.setMultiSelectionEnabled(true);
            open.setCurrentDirectory(new File(System
                    .getProperty("user.home") + "/Desktop"));
            open.setDialogTitle("Which File Would You Like to Open?");
            open.setDragEnabled(true);
            int actionDialog = open.showOpenDialog(null);
            if (actionDialog != JFileChooser.APPROVE_OPTION) {
                return;
            } else {
                log("Done!", true);
                String name = open.getSelectedFile().getAbsolutePath();
                try {
                    BufferedReader in = new BufferedReader(new FileReader(
                            name));
                    String line;
                    textArea.setText(null);
                    while ((line = in.readLine()) != null) {
                        appendString(line);
                        appendString(newLine);
                    }
                    in.close();

                } catch (IOException ioe) {
                    ioe.fillInStackTrace();
                } catch (BadLocationException e1) {
                }
            }

        }
    });

    frame.setSize(500, 320);
    frame.setJMenuBar(menuBar);
    frame.setVisible(true);
}

static public void appendString(String str) throws BadLocationException {
    StyledDocument document = (StyledDocument) textArea.getDocument();
    document.insertString(document.getLength(), str, null);
}

static private void log(String msg, boolean remove) {
    label1 = new JLabel(msg);
    if (remove) {
        paneText.removeAll();
    }
    paneText.add(label1);
    paneText.validate();
    pane.validate();
    new Thread() {
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
            paneText.removeAll();
            label1 = new JLabel("          ");
            paneText.add(label1);
            paneText.validate();
            pane.validate();
        }
    }.start();
}

class UndoHandler implements UndoableEditListener {

    public void undoableEditHappened(UndoableEditEvent e) {
        undoManager.addEdit(e.getEdit());
        undoAction.update();
        redoAction.update();
    }
}

static class UndoAction extends AbstractAction {
    public UndoAction() {
        super("Undo");
        setEnabled(false);
    }

    public void actionPerformed(ActionEvent e) {
        try {
            undoManager.undo();
        } catch (CannotUndoException ex) {
            // TODO deal with this
            // ex.printStackTrace();
        }
        update();
        redoAction.update();
    }

    protected void update() {
        if (undoManager.canUndo()) {
            setEnabled(true);
            putValue(Action.NAME, undoManager.getUndoPresentationName());
        } else {
            setEnabled(false);
            putValue(Action.NAME, "Undo");
        }
    }
}

static class RedoAction extends AbstractAction {
    public RedoAction() {
        super("Redo");
        setEnabled(false);
    }

    public void actionPerformed(ActionEvent e) {
        try {
            undoManager.redo();
        } catch (CannotRedoException ex) {
            // TODO deal with this
            ex.printStackTrace();
        }
        update();
        undoAction.update();
    }

    protected void update() {
        if (undoManager.canRedo()) {
            setEnabled(true);
            putValue(Action.NAME, undoManager.getRedoPresentationName());
        } else {
            setEnabled(false);
                putValue(Action.NAME, "Redo");
            }
        }
    }
}

Solution

  • You have not instantiated menuEdit, only declared it. You need to add this line somewhere before it is used:

    menuEdit = new JMenu("Edit.");
    

    When you get a NullPointerException It's easy to be drawn towards the arguments of a method/function as the source of the problem. It's important to remember to check that all the objects on the line being referenced actually have an instance otherwise you'll find yourself on a wild goose chase!