2013-07-31 46 views
3

有必要製作一個自定義控制檯。我有以下代碼:如何製作自定義的Java/JavaFX控制檯?

public class Console extends OutputStream{ 

private Console(ResourceBundle resourceBundle) throws IOException { 
    FXMLLoader loader = new FXMLLoader(this.getClass().getResource("Console.fxml"), resourceBundle); 
    controller = loader.getController(); 
    Scene scene = new Scene((Parent) loader.load()); 
    stage = new Stage(); 
    stage.setScene(scene); 
    show(); 
} 

@Override 
public void write(int b) throws IOException { 
    controller.append(b); 
} 

public static Console getInstance(ResourceBundle resourceBundle) { 
    if (console == null) { 
     try { 
      console = new Console(resourceBundle); 
     } catch (IOException e) { 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 
    } 
    return console; 
} 

public void show() { 
    stage.show(); 
} 

private static Console console = null; 
private ConsoleController controller; 
private Stage stage; 
} 

控制器文件:

public class ConsoleController implements Initializable { 

@Override 
public void initialize(URL url, ResourceBundle resourceBundle) { 
} 

@FXML 
public void append(int i) { 
    textArea.appendText(String.valueOf((char) i)); 
} 

@FXML 
private TextArea textArea; 
} 

而所有這些都是從被稱爲 '開始()':

@Override 
public void start(Stage primaryStage) throws IOException { 
    ... 
    System.setErr(new PrintStream(Console.getInstance(rb))); 
} 

在異常沒有被印在Console.fxmltextArea,但引發以下異常:

異常在線程「的JavaFX應用程序線程」 例外:顯示java.lang.NullPointerException在線程「的JavaFX應用程序線程」

什麼我做錯了從UncaughtExceptionHandler的拋出?

------ 編輯 --------

理解,它是需要使用多個線程後,我有以下代碼:

public class Console{ 
private Console(ResourceBundle resourceBundle) throws IOException { 
    FXMLLoader loader = new FXMLLoader(this.getClass().getResource("Console.fxml"), resourceBundle); 
    Parent root = (Parent) loader.load(); 
    controller = loader.getController(); 
    Scene scene = new Scene(root); 
    stage = new Stage(); 
    stage.setScene(scene); 
    show(); 

    if (errorOutputThread != null) { 
     errorOutputThread.interrupt(); 
     try { 
      errorOutputThread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 
     errorOutputThread = null; 
    } 

    if (outOutputThread != null) { 
     outOutputThread.interrupt(); 
     try { 
      outOutputThread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 
     outOutputThread = null; 
    } 

    System.err.flush(); 
    System.out.flush(); 

    outPipedInputStream = new PipedInputStream(); 
    outPipedOutputStream = new PipedOutputStream(outPipedInputStream); 
    System.setOut(new PrintStream(outPipedOutputStream)); 

    errorPipedInputStream = new PipedInputStream(); 
    errorPipedOutputStream = new PipedOutputStream(errorPipedInputStream); 
    System.setErr(new PrintStream(errorPipedOutputStream)); 

    outOutputThread = new Thread(new ConsoleStream(outPipedInputStream, "OUT")); 
    outOutputThread.setDaemon(true); 
    outOutputThread.start(); 

    errorOutputThread = new Thread(new ConsoleStream(errorPipedInputStream, "ERROR")); 
    errorOutputThread.setDaemon(true); 
    errorOutputThread.start(); 

    controller.appendText("Start Console"); 

} 

public static Console getInstance(ResourceBundle resourceBundle) { 
    if (console == null) { 
     try { 
      console = new Console(resourceBundle); 
     } catch (IOException e) { 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 
    } 
    return console; 
} 

public void show() { 
    stage.show(); 
} 

private class ConsoleStream implements Runnable { 
    private ConsoleStream(InputStream in, String type) { 
     inputStream = in; 
     this.type = type; 
    } 

    public void run() { 
     try { 
      InputStreamReader is = new InputStreamReader(inputStream); 
      BufferedReader br = new BufferedReader(is); 
      String read = null; 
      read = br.readLine(); 
      while(read != null) { 
       controller.appendText(read + "\n"); 
       read = br.readLine(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 
     } 
     controller.appendText("Thread" + type + "started"); 

    } 

    private final InputStream inputStream; 
    private String type; 
} 

private static Console console = null; 
private ConsoleController controller; 
private Stage stage; 
private PrintStream printStream; 
private PipedOutputStream customPipedOutputStream; 
private PipedOutputStream errorPipedOutputStream; 
private PipedOutputStream outPipedOutputStream; 
private PipedInputStream customPipedInputStream; 
private PipedInputStream errorPipedInputStream; 
private PipedInputStream outPipedInputStream; 
private Thread customOutputThread; 
private Thread outOutputThread; 
private Thread errorOutputThread; 
} 

但結果只是:「啓動控制檯」,沒有結果controller.appendText("Thread" + type + "started");,所以看起來這個線程沒有啓動。但爲什麼?

+0

東西是空(我不知道是什麼)。 [Java 8](http://jdk8.java.net/download.html)允許你[爲JavaFX應用程序線程設置未捕獲的異常處理程序](https://javafx-jira.kenai.com/browse/RT -15332)。也許如果你在Java 8中測試你的應用程序並設置了一個未捕獲的異常處理程序,你將能夠獲得更多的信息(如堆棧跟蹤),這可能會幫助你調試你的問題。 – jewelsea

+0

您可能也對[系統錯誤和系統輸出控制檯記錄器](https://github.com/jewelsea/conception/blob/master/src/org/jewelsea/conception/LogArea.java)感興趣,我爲JavaFX迷你IDE項目。這可能不是處理這種問題的最有效的方式,但它對我有效。 – jewelsea

+0

@jewelsea:我使用了你的記錄器代碼,並且明白我需要單獨的控制檯線程。現在我有另一個問題 - 這些線程不想開始。 – Eugene

回答

2

我認爲你必須加載窗體,然後才能拿到控制器實例

FXMLLoader loader = new FXMLLoader(this.getClass().getResource("Console.fxml"),resourceBundle); 
Parent p = (Parent) loader.load() 
controller = loader.getController(); 
Scene scene = new Scene(p);