簡體   English   中英

帶計時器的空指針異常

[英]Null Pointer Exception with a timer

我的任務有問題:我需要編寫一個帶有計時器組件的游戲,但出現“線程“Timer-0”中的異常 java.lang.NullPointerException”錯誤。 我正在使用最新版本的 eclipse。 幫助將不勝感激。

實際錯誤:

線程“Timer-0”中的異常 java.lang.NullPointerException at GameFrame$MyTimerTask.run(GameFrame.java:152) at java.util.TimerThread.mainLoop(Unknown Source) at java.util.TimerThread.run(Unknown Source)

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class GameFrame extends JFrame implements ActionListener {

    private final int NUM_BUTTONS1 = 5;
    private final int NUM_BUTTONS2 = 8;
    private final int NUM_BUTTONS3 = 10;
    private final int NUM_LEVELS = 3;

    private int[] columns,lines;
    private int current_size,hours,minutes,seconds,score,selection_counter;
    private int c1,c2,c3,c4,l1,l2,l3,l4;

    private Color color1,color2,color3,color4;
    private JButton [] buttons,selection;
    private JButton [] levels;
    private JPanel buttons_panel,levels_panel;
    private JTextField timer_field,score_field;
    private Timer timer;

    public GameFrame() {
        current_size = NUM_BUTTONS1;
        setLayout(new BorderLayout());
        buttons_panel = new JPanel();
        buttons_panel.setLayout(new GridLayout(NUM_BUTTONS1,NUM_BUTTONS1));
        //setup buttons
        buttons = new JButton[NUM_BUTTONS3 * NUM_BUTTONS3];
        for(int i = 0; i < buttons.length; i++) {
            buttons[i] = new JButton();
            switch((int)(Math.random() * 4)) {
                case 0:
                    buttons[i].setBackground(Color.BLUE);
                    break;
                case 1:
                    buttons[i].setBackground(Color.RED);
                    break;
                case 2:
                    buttons[i].setBackground(Color.GREEN);
                    break;
                case 3:
                    buttons[i].setBackground(Color.YELLOW);
                    break;
            }
        buttons[i].addActionListener(this);     
        }
        //add buttons to layout
        for(int i = 0; i < NUM_BUTTONS1 * NUM_BUTTONS1; i++)
            buttons_panel.add(buttons[i]);

        levels_panel = new JPanel();
        levels_panel.setLayout(new GridLayout(3,1));
        levels = new JButton[NUM_LEVELS];
        for(int i = 0; i < levels.length; i++) {
            levels[i] = new JButton("level "+ (i + 1));
            levels[i].addActionListener(this);
            levels_panel.add(levels[i]);
        }

        selection_counter = 0;
        selection = new JButton[4];
        columns = new int [4];
        lines = new int [4];

        hours = 0;
        minutes = 0;
        seconds = 0;
        timer = new Timer();
        timer.schedule(new MyTimerTask(), 0,1000);

        timer_field = new JTextField();
        timer_field.setText(hours + ":" + minutes + ":" + seconds);
        timer_field.setFont(new Font("random",0,50));
        timer_field.setHorizontalAlignment(JTextField.CENTER);
        timer_field.setBackground(Color.white);
        timer_field.setForeground(Color.green);
        add(timer_field,BorderLayout.SOUTH);

        score_field = new JTextField();
        score_field.setText("Game Score: " + score);
        score_field.setFont(new Font("random",0,50));
        score_field.setHorizontalAlignment(JTextField.CENTER);
        score_field.setBackground(Color.white);
        score_field.setForeground(Color.green);
        add(score_field,BorderLayout.NORTH);

        //add buttons layout and levels buttons layout
        add(buttons_panel,BorderLayout.CENTER);
        add(levels_panel,BorderLayout.WEST);
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        //change levels
        if (event.getSource() == levels[0] || event.getSource() == levels[1] || event.getSource() == levels[2]) {
            if (event.getSource() == levels[0])
                current_size = NUM_BUTTONS1;
            else if (event.getSource() == levels[1])
                current_size = NUM_BUTTONS2;
            else if (event.getSource() == levels[2])
                current_size = NUM_BUTTONS3;
            buttons_panel.removeAll();
            //redefine grid Layout to match the new current_size
            buttons_panel.setLayout(new GridLayout(current_size, current_size));
            for(int i = 0; i < current_size * current_size; i++)
                buttons_panel.add(buttons[i]);
            newGame(); //changing levels requires starting a new game
        }
        //select a rectangle on the board
        else if (event.getSource() instanceof JButton) {
            selection[selection_counter++] = (JButton)event.getSource();
            if (selection_counter == 4) {
                selection_counter = 0;

                columns = findCoordinates(true);
                lines = findCoordinates(false);

                if (buttonsSelectionCheck()) {
                    updateBoard();
                }
            }

        }
        //update the window
        timer_field.setText(hours + ":" + minutes + ":" + seconds);
        score_field.setText("Game Score: " + score);
        buttons_panel.validate();
        repaint();      
    }

    public class MyTimerTask extends TimerTask {
        public void run() {
            seconds++;
            if (seconds == 60) {
                minutes++;
                seconds = 0;
            }
            if (minutes == 60) {
                hours++;
                minutes = 0;
            }
            timer_field.setText(hours + ":" + minutes + ":" + seconds);
        }
    }

    private void newGame() {
        score = 0;
        seconds = 0;
        minutes = 0;
        hours = 0;
        selection_counter = 0;
        selection[0] = null;
        selection[1] = null;
        selection[2] = null;
        selection[3] = null;

        for(int i = 0; i < buttons.length; i++) {
            switch((int)(Math.random() * 4)) {
                case 0:
                    buttons[i].setBackground(Color.BLUE);
                    break;
                case 1:
                    buttons[i].setBackground(Color.RED);
                    break;
                case 2:
                    buttons[i].setBackground(Color.GREEN);
                    break;
                case 3:
                    buttons[i].setBackground(Color.YELLOW);
                    break;
            }
        }       
    }

    private int[] findCoordinates(boolean choice) {
        int[] columns = new int[4];
        int[] lines = new int[4];

        for (int i = 0; i < selection.length; i++)
            for (int j = 0; j < buttons.length; j++)
                if (selection[i] == buttons[j]) {
                    if (choice)
                        columns[i] = j%current_size;
                    else
                        lines[i] = j/current_size;
                }
        if (choice)
            return columns;
        else
            return lines;
    }   

    public boolean buttonsSelectionCheck() {
        c1 = columns[0];
        c2 = columns[1];
        c3 = columns[2];
        c4 = columns[3];
        l1 = lines[0];
        l2 = lines[1];
        l3 = lines[2];
        l4 = lines[3];
        color1 = selection[0].getBackground();
        color2 = selection[1].getBackground();
        color3 = selection[2].getBackground();
        color4 = selection[3].getBackground();

        if (color1 != Color.GRAY && color1 == color2 && color2 == color3 && color3 == color4)
            if (c1 == c4 && c2 == c3 && l1 == l2 && l3 == l4 ) { 
                return true;
            }
        return false;
    }

    private void updateBoard() {
        int b_column,b_line;

        for (int i = 0; i < (current_size * current_size); i++) {
            b_column = i%current_size;
            b_line = i/current_size;
            if (b_column >= c1 && b_column <= c2 && b_line >= l1 && b_line <= l4) {
                if (buttons[i].getBackground() != Color.GRAY)
                    score+=10;
                buttons[i].setBackground(Color.GRAY);
            }
        }
    }

}

此行導致 MyTimerTask 實例以 0 的延遲(無延遲)執行。

timer.schedule(new MyTimerTask(), 0,1000);

MyTimerTask 訪問字段timer_field ,該字段在調度語句之后初始化。

timer_field = new JTextField();

所以timer_field仍然是null

解決方案:

    // timer.schedule(new MyTimerTask(), 0,1000);

    timer_field = new JTextField();
    timer_field.setText(hours + ":" + minutes + ":" + seconds);
    timer_field.setFont(new Font("random",0,50));
    timer_field.setHorizontalAlignment(JTextField.CENTER);
    timer_field.setBackground(Color.white);
    timer_field.setForeground(Color.green);

    timer.schedule(new MyTimerTask(), 0,1000);

所以調度調用應該晚一點。

您的內部類 MyTimerTask 在初始化之前使用 timer_field。 你可以移動這些行:

timer = new Timer();
timer.schedule(new MyTimerTask(), 0,1000);

到構造函數的末尾,以便在初始化 timer_field 的這個之后:

timer_field = new JTextField();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM