2015-11-03 22 views
0

EDIT 4

我創建了一個簡單的例子,應該給你發生的事情,現在的想法產生。JavaFX的:控制檯輸出重定向到文本區是在SceneBuilder

現在發生的事情是,只要我點擊按鈕向TextArea打印「HELLO WORLD」,程序就會掛起並使用100%的CPU。 Eclipse控制檯面板中也沒有輸出。

Main.java

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     try { 
      Parent root = FXMLLoader.load(getClass().getResource("/application/test.fxml")); 
      Scene scene = new Scene(root); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 


     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

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

MainController.java

public class MainController { 

    @FXML 
    private TextArea console; 
    private PrintStream ps = new PrintStream(new Console(console)); 

    public void button(ActionEvent event) { 
     System.setOut(ps); 
     System.setErr(ps); 
     System.out.println("Hello World"); 
    } 

    public class Console extends OutputStream { 
     private TextArea console; 

     public Console(TextArea console) { 
      this.console = console; 
     } 

     public void appendText(String valueOf) { 
      Platform.runLater(() -> console.appendText(valueOf)); 
     } 

     public void write(int b) throws IOException { 
      appendText(String.valueOf((char)b)); 
     } 
    } 
} 

編輯2:看來我的問題是太長,很難理解。我正在重組這個中間。


編輯3

我想我應該只是顯示這裏的一切。我想要做的是一個CLI應用程序的簡單GUI前端。我是CS學生,Java是我們的主要語言,所以這主要是爲了練習。


我一直在尋找每個小時和幾小時的地方,但仍然沒有解決方案。我嘗試過像以前一樣使用Swing。該方法在Swing中運行良好,但與JavaFX無關。

這是我(目前)logger.java類:

package application; 

import java.io.*; 
import java.net.URL; 
import java.util.ResourceBundle; 

import javafx.application.Platform; 
import javafx.fxml.Initializable; 
import javafx.scene.control.*; 

public class ytdlLogger extends OutputStream implements Initializable 
{ 
    private TextArea loggerPane; 

    public ytdlLogger(TextArea loggerPane) { 
     this.loggerPane = loggerPane; 
    } 

    public void appendText(String valueOf) { 
     Platform.runLater(() -> loggerPane.appendText(valueOf)); 
    } 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
     OutputStream out = new OutputStream() { 
      @Override 
      public void write(int b) throws IOException { 
       appendText(String.valueOf((char)b)); 
      } 
     }; 
     System.setOut(new PrintStream(out, true)); 
     System.setErr(new PrintStream(out, true)); 
    } 

    @Override 
    public void write(int b) throws IOException { 
     // TODO Auto-generated method stub 

    } 
} 

我不認爲有任何這方面的實際問題。我也添加了PrintStream對象,將MainController類中的System.setOut和System.setErr重定向到TextArea,但它也不起作用。

我也有另一個主類,這是加載FXML的主要事情。我嘗試重定向從那裏輸出,它幾乎工作。差不多,因爲我停止在Eclipse內看到控制檯輸出,我知道這是一個很大的進步。

那麼,這裏似乎是什麼問題?是因爲FXML嗎?我絕對是Java和JavaFX的初學者,這是我的第一個JavaFX應用程序。任何指導非常感謝。先謝謝你。


編輯1

這裏的主要類:

package application; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.stage.Stage; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     try { 
      Parent root = FXMLLoader.load(getClass().getResource("/application/Main.fxml")); 
      Scene scene = new Scene(root); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

有什麼異常? – ItachiUchiha

+0

如果文本區域是在場景構建器中創建的,它應該有一個'@FXML'註釋。否則它會認爲它是一個不同的對象。 –

+0

你可以顯示你的'Main'類的代碼嗎?問題不在於你在記錄器中實現了'write(...)'方法嗎? –

回答

1

你之前用的console值初始化ps已由FXMLLoader初始化。即你有

@FXML 
private TextArea console; 
private PrintStream ps = new PrintStream(new Console(console)); 

顯然console仍然null,當你把它傳遞給new Console(...)

FXMLLoader已初始化注入的字段,您可以使用initialize方法執行操作後,您需要初始化ps

SSCCE:

MainController.java:

package application; 

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

import javafx.application.Platform; 
import javafx.event.ActionEvent; 
import javafx.fxml.FXML; 
import javafx.scene.control.TextArea; 

public class MainController { 

    @FXML 
    private TextArea console; 
    private PrintStream ps ; 

    public void initialize() { 
     ps = new PrintStream(new Console(console)) ; 
    } 

    public void button(ActionEvent event) { 
     System.setOut(ps); 
     System.setErr(ps); 
     System.out.println("Hello World"); 
    } 

    public class Console extends OutputStream { 
     private TextArea console; 

     public Console(TextArea console) { 
      this.console = console; 
     } 

     public void appendText(String valueOf) { 
      Platform.runLater(() -> console.appendText(valueOf)); 
     } 

     public void write(int b) throws IOException { 
      appendText(String.valueOf((char)b)); 
     } 
    } 
} 

Main.java:

package application; 

import javafx.application.Application; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 


public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     try { 
      Parent root = FXMLLoader.load(getClass().getResource("test.fxml")); 
      Scene scene = new Scene(root); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

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

test.fxml:

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.layout.BorderPane?> 
<?import javafx.scene.control.TextArea?> 
<?import javafx.scene.control.Button?> 
<?import javafx.geometry.Insets?> 

<BorderPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController"> 
    <center> 
     <TextArea fx:id="console"/> 
    </center> 
    <bottom> 
     <Button onAction="#button" text="Output"> 
      <BorderPane.alignment>CENTER</BorderPane.alignment> 
      <BorderPane.margin><Insets top="5" left="5" right="5" bottom="5"/></BorderPane.margin> 
     </Button> 
    </bottom> 
</BorderPane> 
+0

非常感謝。這工作得很好。它對我的程序也是非常好的。但是我怎樣才能使System.setOut從一開始就被設置,而不僅僅是當按鈕被按下時呢?說如果我有幾個按鈕,是否必須在每種方法中使用'System.setOut'? –

+0

如果您努力停下來思考我的解決方案爲什麼可行,爲什麼您的原始代碼沒有這樣做,那麼您就不需要問這個問題。停止複製代碼並開始嘗試理解它在做什麼。 –

+0

不,它工作得很好,我沒有任何麻煩實施它。我試圖記錄每一種實現的方法和代碼,以便我理解它的作用,這一切都是爲了我自己的理解。 –

1

你不與FXMLLoader使用您的控制器。否則你會得到一個異常,因爲這個類沒有默認的構造函數。

如果你想使用FXMLLoader創建您ytdlLogger,添加屬性fx:controller="application.ytdlLogger"(其中fx是FXML命名空間前綴)添加到您FXML文件的根元素。

如果你想做到這一點,還需要改變一些東西:

  • ytdlLogger需要一個默認的構造函數(即要麼刪除您的構造函數或創建不帶參數的一個新的)。

  • @FXML註釋添加到您的loggerPane場,讓FXMLLoader訪問場與fx:id="loggerPane"屬性給它分配TextArea

  • 更好地從控制器中刪除基類OutputStream,因爲您不使用它。
  • 添加一些打印到System.outSystem.err的代碼。否則沒有什麼會寫入TextArea。確保在控制器初始化後執行此操作。

你的控制器看起來應該是這樣的變化後:

public class ytdlLogger implements Initializable 
{ 

    @FXML 
    private TextArea loggerPane; 

    public void appendText(String valueOf) { 
     Platform.runLater(() -> loggerPane.appendText(valueOf)); 
    } 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
     OutputStream out = new OutputStream() { 
      @Override 
      public void write(int b) throws IOException { 
       appendText(String.valueOf((char)b)); 
      } 
     }; 
     System.setOut(new PrintStream(out, true)); 
     System.setErr(new PrintStream(out, true)); 
    } 

} 

而且FXML應該類似於此

<?xml version="1.0" encoding="UTF-8"?> 

<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" 
      fx:controller="application.ytdlLogger"> <!-- controller goes here --> 
    <children> 
     <TextArea fx:id="loggerPane" /> <!-- the TextArea you want to use for logging --> 
    </children> 
</AnchorPane> 
+0

我沒有在控制器中使用FXMLLoader,而是在加載FXML的Main類中。控制器位於不同的類「MainController」中。在MainController內部是FXML爲TextArea和其他文件的'fx:id'找到的地方。 –

+0

我嘗試在Main.java類中添加'System.setOut'和'System.setErr',或者甚至在按鈕確實是它的實際作業之前,它在其中加載進程。 Eclipse中的控制檯變成空白,程序將掛起並耗盡我的資源,而不是無所事事。 –

+0

我想我的問題還不夠清楚。我已經包括了一切,所以你可以得到我想要做的。抱歉。 –

相關問題