Java 为什么我按下“时会出现NullPointerException”;新游戏;?

Java 为什么我按下“时会出现NullPointerException”;新游戏;?,java,swing,awt,Java,Swing,Awt,我正在制作数独游戏的控制器。当您运行我的SudokuMain.java文件,并单击页面顶部的“文件”,然后选择“新建游戏”时,我得到异常: 线程“AWT-EventQueue-0”java.lang.NullPointerException中出现异常 我有一个用于“新游戏”的ActionListener来创建一个名为“CreateBoard”的JDialog对象,并提示用户输入“每个区域的行数”和“每个区域的列数”,然后按“CreateBoard”,或者按“Cancel”将其删除 我不确定我做错

我正在制作数独游戏的控制器。当您运行我的SudokuMain.java文件,并单击页面顶部的“文件”,然后选择“新建游戏”时,我得到异常:

线程“AWT-EventQueue-0”java.lang.NullPointerException中出现异常

我有一个用于“新游戏”的ActionListener来创建一个名为“CreateBoard”的JDialog对象,并提示用户输入“每个区域的行数”和“每个区域的列数”,然后按“CreateBoard”,或者按“Cancel”将其删除

我不确定我做错了什么,但我觉得问题在于内部类菜单。感谢您的帮助

// Allow short name access to following classes
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

public class SudokuMain extends JComponent {

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

  private SudokuBase board;
  private SudokuView view;

  private JFrame win;
  private JPanel center;
  private JPanel west;
  private JPanel east;
  private JPanel cells;

  private final Dialog1 setWin1;

  public SudokuMain() {

   // start game
   view = new SudokuView(makeBoard());
   board = makeBoard();

   win = new JFrame("Sudoku");
   center = new JPanel();
   west = new JPanel();
   east = new JPanel();

   // "player" cells for current Sudoku board
   cells = new SetSymbols(view);
   // the 1st set-up window
   setWin1 = new Dialog1(this, "New Game", true);

   // create menu bar
   MenuAtTop menuBar = new MenuAtTop(this);
   win.setJMenuBar(menuBar);

   win.setLayout(new BorderLayout());
   view.setSelected(1, 1);
   west.setLayout(new BorderLayout());
   east.setLayout(new BorderLayout());
   center.setLayout(new FlowLayout());

   west.add(cells);
   east.add(view, BorderLayout.CENTER);
   center.add(west);
    center.add(east);

   win.add(center);

   win.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
   win.pack();
   win.setVisible(true);

 }

class SudokuControlButton extends JPanel {

  private int row;
  private int col;

  // row of selected cell
  private int selRow;
  // column of selected cell
  private int selCol;

  // the value that corresponds with the desired symbol
  private int value;

  /**
   * Constructs SudokuControlButton object; the graphic "button"
   * to control the board.
   */
  public SudokuControlButton(final SudokuView view) {

    setPreferredSize(new Dimension(40, 40));
    setBackground(Color.LIGHT_GRAY);

    //value = 0;

    addMouseListener(new MouseListener() {

      public void mouseClicked(MouseEvent e) {
        selRow = view.getSelectedRow();
        selCol = view.getSelectedColumn();

        if(!board.isGiven(selRow, selCol)) {
          board.setValue(selRow, selCol, value);

        view.repaint();
        } else {  // have system beep sound
          getToolkit().beep();
        }

        repaint();
      }

      public void mouseEntered(MouseEvent e){
        // set to "highlighted" color
        setBackground(Color.WHITE);

        repaint();
      }

      public void mouseExited(MouseEvent e){
        // set to default color
        setBackground(Color.LIGHT_GRAY);

        repaint();
      }

      public void mousePressed(MouseEvent e){
        // set to "active" color
        setBackground(Color.YELLOW);

        repaint();
      }

      public void mouseReleased(MouseEvent e){
      }

    });
  }

  public void paintComponent(Graphics g) {
    super.paintComponent(g);

    switch(value) {
      case 0:
      drawSymbol(g, 0);
      break;
    case 1:
      drawSymbol(g, 1);
      break;
    case 2:
      drawSymbol(g, 2);
      break;
    case 3:
      drawSymbol(g, 3);
      break;
    case 4:
      drawSymbol(g, 4);
      break;
    case 5:
      drawSymbol(g, 5);
      break;
    case 6:
      drawSymbol(g, 6);
      break;
    case 7:
      drawSymbol(g, 7);
      break;
    case 8:
      drawSymbol(g, 8);
      break;
    case 9:
      drawSymbol(g, 9);
      break;
    case 10:
      drawSymbol(g, 10);
      break;
    case 11:
      drawSymbol(g, 11);
      break;
    case 12:
      drawSymbol(g, 12);
      break;
  }

}

/**
 * This method draws the symbol that corresponds with 
 * the specified value (0-12).
 * 
 * @param g The drawing mechanism.
 * @param value The specified value.
 */
public void drawSymbol(Graphics g, int value) {

  if(value < 0 || value > 12) {
    String msg = "Value cannot be less than 1 or greater than 12.";
    throw new IllegalArgumentException(msg);
  }

  // enable drawing with "thick" lines
  Graphics2D g2 = (Graphics2D) g;
  g2.setStroke(new BasicStroke(3));

  switch(value) {
    case 0:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      break;
    case 1:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      break;
    case 2:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      break;
    case 3:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      g2.drawLine(15, 5, 15, 45);
      break;
    case 4:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      g2.drawLine(15, 5, 15, 45);
      g2.drawLine(20, 5, 20, 45);
      break;
    case 5:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      g2.drawLine(15, 5, 15, 45);
      g2.drawLine(20, 5, 20, 45);
      g2.drawLine(25, 5, 25, 45);
      break;
    case 6:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 45);
      g2.drawLine(10, 5, 10, 45);
      g2.drawLine(15, 5, 15, 45);
      g2.drawLine(20, 5, 20, 45);
      g2.drawLine(25, 5, 25, 45);
      g2.drawLine(30, 5, 30, 45);
      break;
    case 7:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 20);
      g2.drawLine(10, 5, 10, 20);
      g2.drawLine(15, 5, 15, 20);
      g2.drawLine(20, 5, 20, 20);
      g2.drawLine(25, 5, 25, 20);
      g2.drawLine(30, 5, 30, 20);
      g2.drawLine(5, 30, 5, 45);
      break;
    case 8:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 20);
      g2.drawLine(10, 5, 10, 20);
      g2.drawLine(15, 5, 15, 20);
      g2.drawLine(20, 5, 20, 20);
      g2.drawLine(25, 5, 25, 20);
      g2.drawLine(30, 5, 30, 20);
      g2.drawLine(5, 30, 5, 45);
      g2.drawLine(10, 30, 10, 45);
      break;
    case 9:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g2.drawLine(5, 5, 5, 20);
      g2.drawLine(10, 5, 10, 20);
      g2.drawLine(15, 5, 15, 20);
      g2.drawLine(20, 5, 20, 20);
      g2.drawLine(25, 5, 25, 20);
      g2.drawLine(30, 5, 30, 20);
      g2.drawLine(5, 30, 5, 45);
      g2.drawLine(10, 30, 10, 45);
      g2.drawLine(15, 30, 15, 45);
      break;
    case 10:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g.drawLine(5, 5, 5, 20);
      g.drawLine(10, 5, 10, 20);
      g.drawLine(15, 5, 15, 20);
      g.drawLine(20, 5, 20, 20);
      g.drawLine(25, 5, 25, 20);
      g.drawLine(30, 5, 30, 20);
      g.drawLine(5, 30, 5, 45);
      g.drawLine(10, 30, 10, 45);
      g.drawLine(15, 30, 15, 45);
      g.drawLine(20, 30, 20, 45);
      break;
    case 11:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g.drawLine(5, 5, 5, 20);
      g.drawLine(10, 5, 10, 20);
      g.drawLine(15, 5, 15, 20);
      g.drawLine(20, 5, 20, 20);
      g.drawLine(25, 5, 25, 20);
      g.drawLine(30, 5, 30, 20);
      g.drawLine(5, 30, 5, 45);
      g.drawLine(10, 30, 10, 45);
      g.drawLine(15, 30, 15, 45);
      g.drawLine(20, 30, 20, 45);
      g.drawLine(25, 30, 25, 45);
      break;
    case 12:
      // draw borders
      g.drawRect(0, 0, 50, 50);
      // draw symbol
      g.drawLine(5, 5, 5, 20);
      g.drawLine(10, 5, 10, 20);
      g.drawLine(15, 5, 15, 20);
      g.drawLine(20, 5, 20, 20);
      g.drawLine(25, 5, 25, 20);
      g.drawLine(30, 5, 30, 20);
      g.drawLine(5, 30, 5, 45);
      g.drawLine(10, 30, 10, 45);
      g.drawLine(15, 30, 15, 45);
      g.drawLine(20, 30, 20, 45);
      g.drawLine(25, 30, 25, 45);
      g.drawLine(30, 30, 30, 45);
      break;
    }

  }

 }

class MenuAtTop extends JMenuBar implements ActionListener{

  private SudokuMain main;

  private JMenu fileMenu;
  private JMenuItem newGame;

  private JDialog createNewWin; 

  public MenuAtTop(final SudokuMain m) {

    fileMenu = new JMenu("File");
    add(fileMenu);

    newGame = new JMenuItem("New Game");
    newGame.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,
                                                  ActionEvent.CTRL_MASK));
    fileMenu.add(newGame);
    newGame.addActionListener(this);

  }

  public void actionPerformed(ActionEvent e) {
    setEnabled(false);
    createNewWin = new Dialog1(main, "Create New Board", true);
  }

}

class Dialog1 extends JDialog {

  private JTextField rows;
  private JTextField cols;
  private JButton createBoard; 
  private JButton cancel;
  private JLabel rowLabel;
  private JLabel colLabel;
  private JLabel errorMes;


  private JPanel center;
  private JPanel north;
  private JDialog setUpWin2;

  /**
   * Constructs Dialog1 object.
   * 
   * @param win The window containing the dialog box.
   * @param header The title of dialog box.
   * @param modal Whether dialog box is modal or not.
   */
  public Dialog1(final SudokuMain win, String header, boolean modal) {
    // call superclass constructor
    super();

    // instantiate and bind to references
    rows = new JTextField(2);
    cols = new JTextField(2);
    createBoard = new JButton("Create Board");
    cancel = new JButton("Cancel");
    rowLabel = new JLabel("Rows per region: ");
    colLabel = new JLabel("Columns per region: ");
    errorMes = new JLabel();

    north = new JPanel(new FlowLayout());
    center = new JPanel(new FlowLayout());

    // set characteristics
    setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
    setTitle(header);
    setModal(modal);
    setLayout(new BorderLayout());

    // set characteristics of error message
    errorMes.setForeground(Color.RED);
    errorMes.setFont(new Font("Arial", Font.ITALIC, 12));
    errorMes.setVisible(false);

    cancel.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        setVisible(false);
      }
    });

    createBoard.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
        int newRows;
        int newCols;
        int newSize;

        try{
          newRows = Integer.parseInt(rows.getText());
          newCols = Integer.parseInt(cols.getText());
        } catch (NumberFormatException exc) {
          newRows = 0;
          newCols = 0;
        }

        newSize = newRows * newCols;
        // input validation
        if(newSize <= 0 && newSize > 12) {
          errorMes.setText("Rows times columns cannot be greater than 12!");
          errorMes.setVisible(true);
          pack();

        } else{ // valid input
          errorMes.setVisible(false);
          setVisible(false);
          setUpWin2 = new Dialog2(win, "New Sudoku", newRows, newCols, true);
        }
      }});


    // place error message in the center
    center.add(errorMes);

    // place labels for rows and columns at the top 
    north.add(rowLabel);
    north.add(rows);
    north.add(colLabel);
    north.add(cols);

    add(center, BorderLayout.CENTER);
    add(north, BorderLayout.NORTH);

    pack();

    if(!win.win.isVisible()) {
      dispose();
    }

  }
}

class Dialog2 extends JDialog {

  private SudokuView view;

  private JPanel panel;
  private JPanel northPanel;
  private JPanel cells;

  private JButton setGivens; 
  private JButton cancel;

  /**
   * Constructs Dialog2 object.
   * 
   * @param win The window containing the dialog box.
   * @param header The title of the dialog box.
   * @param rows the rows to the new SudokuBoard to be constructed in the dialog box
   * @param cols the columns to the new SudokuBoard to be constructed in the dialog box
   * @param modal boolean value for whether the box is modal or not
   */
  public Dialog2(final SudokuMain mainWin, String header, int rows, int cols,
                 boolean modal) {
    // call superclass constructor
    super();

    // instantiate and bind to references
    view = new SudokuView(new SudokuBoard(rows, cols));
    panel = new JPanel();
    northPanel = new JPanel();
    setGivens = new JButton("Set Givens");
    cancel = new JButton("Cancel");
    cells = new SetSymbols(view);

    // set up characteristics 
    setTitle(header);
    setModal(modal);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setLayout(new FlowLayout());
    panel.setLayout(new BorderLayout());
    northPanel.setLayout(new FlowLayout());


    setGivens.addActionListener(new ActionListener() {

      public void actionPerformed(ActionEvent e) {
        // set "given" cells
        makeBoard().fixGivens();

        // have window refer to new board
        west.remove(mainWin.view);
        mainWin.east.remove(mainWin.cells);

        mainWin.view = view;
        mainWin.cells = cells;

        mainWin.west.add(mainWin.view);
        mainWin.east.add(mainWin.cells);

        setVisible(false);

      }});

    cancel.addActionListener(new ActionListener() {
     public void actionPerformed(ActionEvent e) {
        setVisible(false);
    }});

    // place buttons at the top
    northPanel.add(setGivens);
    northPanel.add(cancel);

    panel.add(view, BorderLayout.CENTER);
    panel.add(northPanel, BorderLayout.NORTH);

    add(panel);
    add(cells);

    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    pack();
    setVisible(true);

  }

}

class SetSymbols extends JPanel {

// temporary board to help create graphic "buttons"
private SudokuBoard tempBd;

/**
 * Constructs SetSymbols object.
 * @param view The SudokuView object for SetSymbols.
 */
public SetSymbols(final SudokuView view) {
  // instantiate and bind to reference
  tempBd = new SudokuBoard(1, board.getBoardSize() + 1);

  setLayout(new GridLayout((tempBd.getBoardSize())/2 + 1, 2));

  for(int colCell = 0; colCell < tempBd.getBoardSize(); colCell++) {

    // cannot be changed after set/instantiated
    final int value = colCell;
    final JPanel cell = new JPanel();
    final Color defaultColor = cell.getBackground();

    // set characteristics
    cell.setBorder(BorderFactory.createLineBorder(Color.BLACK));
    // set value for each graphic "button"
    tempBd.setValue(0, colCell, colCell);
    // add the appropriate symbol to each graphic "button"
    cell.add(view.new SudokuCell(0, colCell, tempBd));

    cell.addMouseListener(new MouseListener() {
      // whether inside graphic "button" or not
      boolean insideCell;

      public void mouseClicked(MouseEvent e) {
        int selRow = view.getSelectedRow();
        int selCol = view.getSelectedColumn();

        if(!board.isGiven(selRow, selCol)) {
          board.setValue(selRow, selCol, value);

          view.repaint();
        }
        else {  // have system beep sound
          cell.getToolkit().beep();
        }

      }

      public void mouseEntered(MouseEvent e) {
        insideCell = true;
        // set to "highlighted" color
        cell.setBackground(Color.WHITE);

        view.repaint();
      }

      public void mouseExited(MouseEvent e) {
        insideCell = false;
        // set to default color
        cell.setBackground(defaultColor);

        view.repaint();
      }

      public void mousePressed(MouseEvent e) {
        // set to "active" color
        cell.setBackground(Color.YELLOW);

        view.repaint();
      }

      public void mouseReleased(MouseEvent e) {
        if(insideCell) {
          cell.setBackground(Color.YELLOW);
        }
        else {  // outside of symbol's cell
          cell.setBackground(defaultColor);
        }

        view.repaint();
      }
    });

    // add graphic "button"
    add(cell);

  }

  // handle possible "empty" graphic "button"
  if(tempBd.getBoardSize() % 2 != 0) {
    JPanel empty = new JPanel();
    empty.setBackground(Color.LIGHT_GRAY);
    empty.setBorder(BorderFactory.createLineBorder(Color.BLACK));
    add(empty);
   }

   }

  }

  public static SudokuBase makeBoard() {
    SudokuBase board = new SudokuBoard(2, 3);
    board.setValue(0, 3, 6);
    board.setValue(0, 5, 1);
    board.setValue(1, 2, 4);
    board.setValue(1, 4, 5);
    board.setValue(1, 5, 3);
    board.setValue(2, 3, 3);
    board.setValue(3, 2, 6);
    board.setValue(4, 0, 2);
    board.setValue(4, 1, 3);
    board.setValue(4, 3, 1);
    board.setValue(5, 0, 6);
    board.setValue(5, 2, 1);
    board.fixGivens();
    return board;
  }

}
//允许短名称访问以下类
导入java.awt.*;
导入java.awt.event.*;
导入javax.swing.*;
导入java.util.*;
公共类SudokuMain扩展了JComponent{
公共静态void main(字符串[]args){
新SudokuMain();
}
私人SudokuBase板;
私人SudokuView视图;
私营部门赢得;
私人杰帕内尔中心;
私人杰帕内尔西;
私人杰帕内尔东区;
私人JPanel细胞;
私有最终对话框1 setWin1;
公共SudokuMain(){
//开始比赛
视图=新的SudokuView(makeBoard());
board=makeBoard();
win=新的JFrame(“数独”);
中心=新的JPanel();
west=新JPanel();
east=新JPanel();
//当前数独板的“玩家”单元
单元格=新的设置符号(视图);
//第一个设置窗口
setWin1=newdialog1(这是“新游戏”,true);
//创建菜单栏
MenuAtTop menuBar=新的MenuAtTop(此菜单);
win.setJMenuBar(菜单栏);
win.setLayout(新的BorderLayout());
视图(1,1);
setLayout(新的BorderLayout());
setLayout(新的BorderLayout());
setLayout(新的FlowLayout());
添加(单元格);
添加(视图、边框布局、中心);
中加(西);
中加(东);
win.add(中心);
win.setDefaultCloseOperation(JFrame.DISPOSE\u ON\u CLOSE);
win.pack();
win.setVisible(true);
}
类SudokuControlButton扩展了JPanel{
私人int row;
私人国际学院;
//选定单元格的行
私家车;
//选定单元格的列
私家车;
//与所需符号对应的值
私有int值;
/**
*构造SudokuControlButton对象;图形“按钮”
*控制董事会。
*/
公共数独控制按钮(最终数独视图){
setPreferredSize(新尺寸(40,40));
立根背景(颜色:浅灰色);
//数值=0;
addMouseListener(新MouseListener(){
公共无效mouseClicked(MouseEvent e){
selRow=view.getSelectedRow();
selCol=view.getSelectedColumn();
如果(!board.isGiven(selRow,selCol)){
线路板设置值(selRow、selCol、value);
view.repaint();
}否则{//系统会发出嘟嘟声
getToolkit().beep();
}
重新油漆();
}
公共无效鼠标事件(鼠标事件e){
//设置为“突出显示”颜色
挫折地面(颜色:白色);
重新油漆();
}
公共无效mouseExited(MouseEvent e){
//设置为默认颜色
立根背景(颜色:浅灰色);
重新油漆();
}
公共无效鼠标按下(MouseEvent e){
//设置为“活动”颜色
挫折地面(颜色:黄色);
重新油漆();
}
公共无效MouseEvent(MouseEvent e){
}
});
}
公共组件(图形g){
超级组件(g);
开关(值){
案例0:
绘图符号(g,0);
打破
案例1:
绘图符号(g,1);
打破
案例2:
绘图符号(g,2);
打破
案例3:
绘图符号(g,3);
打破
案例4:
绘图符号(g,4);
打破
案例5:
绘图符号(g,5);
打破
案例6:
绘图符号(g,6);
打破
案例7:
绘图符号(g,7);
打破
案例8:
绘图符号(g,8);
打破
案例9:
绘图符号(g,9);
打破
案例10:
绘图符号(g,10);
打破
案例11:
绘图符号(g,11);
打破
案例12:
绘图符号(g,12);
打破
}
}
/**
*此方法绘制与对应的符号
*指定的值(0-12)。
* 
*@param g是绘图机制。
*@param value指定的值。
*/
公共空白绘图符号(图形g,int值){
如果(值<0 | |值>12){
String msg=“值不能小于1或大于12。”;
抛出新的IllegalArgumentException(msg);
}
//启用“粗”线绘图
图形2d g2=(图形2d)g;
g2.设定行程(新基本行程(3));
开关(值){
案例0:
//划界
g、 drawRect(0,0,50,50);
打破
案例1:
//划界
g、 drawRect(0,0,50,50);
//绘图符号
g2.抽绳(5,5,5,45);
打破
案例2:
//划界
g、 drawRect(0,0,50,50);
//绘图符号
g2.抽绳(5,5,5,45);
g2.抽绳(10,5,10,45);
打破
案例3:
//划界
g、 drawRect(0,0,50,50);
//绘图符号
g2.抽绳(5,5,5,45);
g2.抽绳(10,5,10,45);
g2.抽绳(15,5,15,45);
打破
案例4:
//划界
g、 drawRect(0,0,50,50);
//绘图符号
g2.抽绳(5,5,5,45);
g2.抽绳(10,5,10,45);
g2.抽绳(15,5,15,45);
g2.抽绳(20,5,20,45);
打破
案例5:
//划界
g、 drawRect(0,0,50,50);
//绘图符号
g2.抽绳(5,5,5,45);
g2.抽绳(10,5,10,45);
g2.抽绳(15,5,15,45);
g2.抽绳(20,5,20,45);
g2.抽绳(25,5,25,45);
打破
案例6:
//划界
g、 drawRect(0,0,50,50);
//绘图符号
g2.抽绳(5,5,5,45);
g2.抽绳(10,5,10,45);
g2.抽绳(15,5,15,45);
g2.抽绳(20,5,20,45);
G