GUI程序在java中的内部操作执行方法中冻结一次

GUI程序在java中的内部操作执行方法中冻结一次,java,swing,user-interface,nullpointerexception,Java,Swing,User Interface,Nullpointerexception,我试图将我的system.out.println重定向到GUI的JTextArea元素的dislpay(因此它是公共的和静态的,以便打印内容的方法可以打印到它) 但一旦到了底线: System.out.println("sdsdsdsdsa"); 该程序不再继续。接下来的两行是: System.setOut(printStream); System.setErr(printStream); 它似乎没有打印出来,当我退出程序时,出现以下错误: 异常:从线程“main”中的UncaughtExc

我试图将我的system.out.println重定向到GUI的JTextArea元素的dislpay(因此它是公共的和静态的,以便打印内容的方法可以打印到它)

但一旦到了底线:

System.out.println("sdsdsdsdsa");
该程序不再继续。接下来的两行是:

System.setOut(printStream);
System.setErr(printStream);
它似乎没有打印出来,当我退出程序时,出现以下错误:

异常:从线程“main”中的UncaughtExceptionHandler引发的java.lang.NullPointerException

我无法验证printStream是否为null,因为一旦按下start按钮(JButton1),调试器似乎不会跟随action performed方法

以下是GUI中的主要类:

public class TrainingProgramme {

static PrintStream printStream = new PrintStream(new GUITextOutputStream(TrainingProgrammeGUI.jTextArea1));

 public static void main(String[] args) {

TrainingProgrammeGUI gui = new TrainingProgrammeGUI();
gui.setVisible(true);
System.setOut(printStream);
System.setErr(printStream);

System.out.println("==================================\n"+
                   "* WELCOME TO CATCH ME IF YOU CAN *\n"+
                   "==================================\n");

}
GUI类:

package javaapplication2;

import java.awt.event.ActionEvent;
import java.io.PrintStream;
import java.util.Scanner;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author viljo
 */

public class TrainingProgrammeGUI extends javax.swing.JFrame {

static PrintStream printStream = new PrintStream(new GUITextOutputStream(TrainingProgrammeGUI.jTextArea1));
double startTimer = System.nanoTime();
double stopTimer = 0;
Scanner scan = new Scanner(System.in);
Player gameCharacter = null;
Teacher teacher = null;
int finishedProgram = 0;   
int userChoice = -1;  

/**
 * Creates new form TrainingProgrammeGUI
 */
public TrainingProgrammeGUI() {
    initComponents();
}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 0), new java.awt.Dimension(0, 0), new java.awt.Dimension(32767, 32767));
jLabel1 = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea();
jTextField1 = new javax.swing.JTextField();
jLabel2 = new javax.swing.JLabel();
jButton1 = new javax.swing.JButton();
jButton3 = new javax.swing.JButton();
jLabel3 = new javax.swing.JLabel();
jButton4 = new javax.swing.JButton();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

jLabel1.setFont(new java.awt.Font("Arial", 1, 24)); // NOI18N
jLabel1.setText("CIA Training Programme");

jTextArea1.setColumns(20);
jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1);

jTextField1.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
        jTextField1ActionPerformed(evt);
    }
});

jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
jLabel2.setText("Game: ");

jButton1.setText("Start Game");
jButton1.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton1ActionPerformed(evt);
    }
});

jButton3.setText("What is this game?");
jButton3.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton3ActionPerformed(evt);
    }
});

jLabel3.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
jLabel3.setText("Type Here: ");

jButton4.setText("Exit");
jButton4.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(java.awt.event.ActionEvent evt) {
        jButton4ActionPerformed(evt);
    }
});

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        .addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addGap(159, 159, 159))
    .addGroup(layout.createSequentialGroup()
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(261, 261, 261)
                .addComponent(jLabel1))
            .addGroup(layout.createSequentialGroup()
                .addGap(94, 94, 94)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel2)
                    .addComponent(jLabel3))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 456, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 131, javax.swing.GroupLayout.PREFERRED_SIZE)))
            .addGroup(layout.createSequentialGroup()
                .addGap(170, 170, 170)
                .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(33, 33, 33)
                .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(33, 33, 33)
                .addComponent(jButton4, javax.swing.GroupLayout.PREFERRED_SIZE, 132, javax.swing.GroupLayout.PREFERRED_SIZE)))
        .addContainerGap(175, Short.MAX_VALUE))
);
layout.setVerticalGroup(
    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(jLabel1)
        .addGap(70, 70, 70)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
            .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addComponent(jButton4, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 60, Short.MAX_VALUE)
        .addComponent(filler1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
            .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addComponent(jLabel3))
        .addGap(18, 18, 18)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 226, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addComponent(jLabel2))
        .addGap(20, 20, 20))
);

pack();
}// </editor-fold>



/**
 * @param args the command line arguments
 */
public static void main(String args[]) {
     TrainingProgrammeGUI programme = new TrainingProgrammeGUI();
     programme.setVisible(true);
}

private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {                                            
    // TODO add your handling code here:
}                                           

private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {                                            
    System.out.print("\nThank you for using our training programme!");
    System.exit(0);
}

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    System.out.println("sdsdsdsdsa");
    System.setOut(printStream);
    System.setErr(printStream);
System.out.println("==================================\n"+
                   "* WELCOME TO CATCH ME IF YOU CAN *\n"+
                   "==================================\n");                                     

userChoice = TrainingProgramme.checkInputWithPhrase("1.) Start Game\n2.) What is this game?\n3.) Quit", 1, 3);

teacher = new Teacher("John Doe", "Teacher");

gameCharacter = teacher.introductionLines(); // teacher reads a few lines and asks questions then returns Player class

boolean userFinished = false;
gameCharacter.getHotelRoom().setPlayerHere(true);
do {  // Checks which room player is in then reads instructions for room. Loop finishes when player wants to chooses suspect
    if (gameCharacter.getHotelKitchen().isPlayerHere()) {
    if ("HotelRoom".equals((gameCharacter.getHotelKitchen().instructions(teacher)))) {
        System.out.println("\nRoom chosen!\n");
        gameCharacter.getHotelKitchen().setPlayerHere(false); // Takes player out of current room
        gameCharacter.getHotelRoom().setPlayerHere(true);     // Puts players into chosen room
        }
    } else {
        if ("Choose".equals((gameCharacter.getHotelRoom().instructions(teacher)))) {    
            stopTimer = System.nanoTime();
            Player.timeTaken = (stopTimer - startTimer) / 10000000; //time taken to finish inspecting items (in seconds)
            teacher.chooseWhoDidIt(gameCharacter);
            finishedProgram = 1; //Stop the curret loop
            userFinished = true; //Stop the main menu loop
        } else {
            System.out.println("\nKitchen chosen!\n");
            gameCharacter.getHotelRoom().setPlayerHere(false);// Takes player out of current room
            gameCharacter.getHotelKitchen().setPlayerHere(true);// Puts players into chosen room
        }
    }
} while (userFinished == false);
}  



private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    System.out.println("\n+===========================================================+");
    System.out.println("|This game was created to help train our new junior recruits|");
    System.out.println("+===========================================================+\n\n");

    System.out.println("Objective: Gather evidence by looking for clues\n"+ 
                       "and once you are done go back to the room to guess \n"+
                       "which suspect did it. Suspects are provided once you have\n"+ 
                       "went back to the room and decided to guess who did the crime!\n");
}                                        

// Variables declaration - do not modify                     
private javax.swing.Box.Filler filler1;
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton3;
private javax.swing.JButton jButton4;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JScrollPane jScrollPane1;
public static javax.swing.JTextArea jTextArea1;
private javax.swing.JTextField jTextField1;
// End of variables declaration                   
}

do while循环正在阻止Swing事件线程,使GUI冻结且无用。摆脱该循环,这不是创建事件驱动程序的方式。ActionListener中有一个无限循环。因此,在循环完成之前,GUI无法重新绘制自身。ActionListener应仅用于启动Swing计时器。Th然后,e Swing Timer将安排动画。有关更多信息,请阅读上的Swing教程中的部分。还可以阅读Swing中并发的
目录中的部分,以了解为什么ActionListener中不能有无限循环。请查看@camickr对的回答。您还可以查看可重用的code,允许您重定向输出。但您可能不需要Swing计时器,而是希望查找并创建一种状态机类型的游戏,其中GUI对输入的响应将取决于其当前的“状态”,由键状态字段持有的值。do while循环正在阻止Swing事件线程,使GUI冻结且无用。摆脱循环,这不是创建事件驱动程序的方式。ActionListener中有一个无限循环。因此,在循环完成之前,GUI无法重新绘制自身。ActionListener应该仅用于启动Swing计时器。Swing计时器随后将安排动画。有关详细信息,请阅读上的Swing教程中的部分。还可以阅读Swing中并发的
目录中的部分,以了解为什么ActionListener中不能有无限循环。请查看@camickr对的回答您还可以查看允许重定向输出的可重用代码。但您可能不需要Swing计时器,而是希望查找并创建一种状态机类型的游戏,其中GUI对输入的响应将取决于其当前“状态”,即关键状态字段所持有的值。
package net.codejava.swing;

import java.io.IOException;
import java.io.OutputStream;

import javax.swing.JTextArea;

/**
 * This class extends from OutputStream to redirect output to a JTextArrea
 * @author www.codejava.net
 *
 */
public class CustomOutputStream extends OutputStream {
    private JTextArea textArea;

    public CustomOutputStream(JTextArea textArea) {
        this.textArea = textArea;
    }

    @Override
    public void write(int b) throws IOException {
        // redirects data to the text area
        textArea.append(String.valueOf((char)b));
        // scrolls the text area to the end of data
        textArea.setCaretPosition(textArea.getDocument().getLength());
    }
}