问题
Update:
Still having the same issue, revised source of main app code: http://pastebin.com/fLCwuMVq
There must be something in CoreTest
that blocks the UI, but its doing all sorts of stuff (async xmlrpc requests, async http requests, file io etc), i tried putting it all into runLater
but it doesnt help.
Update 2:
I verified the code runs and produces output correctly but the UI component cant manage to display it for ages
Update 3:
OK I fixed it. I don't know why, but no guide about JavaFX said this, and its very important:
Always put your program logic in a separate thread from the Java FX thread
I had this working with Swing's JTextArea
but for some reason it doesn't work with JavaFX.
I tried debugging and it and doing .getText()
after each write returns what seems to be characters written to it properly, but the actual TextArea
in GUI shows no text.
Did I forgot to somehow refresh it or something?
TextArea ta = TextAreaBuilder.create()
.prefWidth(800)
.prefHeight(600)
.wrapText(true)
.build();
Console console = new Console(ta);
PrintStream ps = new PrintStream(console, true);
System.setOut(ps);
System.setErr(ps);
Scene app = new Scene(ta);
primaryStage.setScene(app);
primaryStage.show();
And the Console
class:
import java.io.IOException;
import java.io.OutputStream;
import javafx.scene.control.TextArea;
public class Console extends OutputStream
{
private TextArea output;
public Console(TextArea ta)
{
this.output = ta;
}
@Override
public void write(int i) throws IOException
{
output.appendText(String.valueOf((char) i));
}
}
Note: this is based on a solution from this answer, I removed bits I didn't care about but unmodified (apart from changing from Swing to JavaFX), it had the same result: data written to the UI element, no data showing on the screen.
回答1:
Have you tried running it on the UI Thread?
public void write(final int i) throws IOException {
Platform.runLater(new Runnable() {
public void run() {
output.appendText(String.valueOf((char) i));
}
});
}
EDIT
I think your problem is that your run some long tasks in the GUI thread, which is going to freeze everything until it completes. I don't know what
CoreTest t = new CoreTest(installPath);
t.perform();
does, but if it takes a few seconds, your GUI won't update during those few seconds. You need to run those tasks in a separate thread.
For the record, this works fine (I have removed the file and CoreTest bits):
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
TextArea ta = TextAreaBuilder.create().prefWidth(800).prefHeight(600).wrapText(true).build();
Console console = new Console(ta);
PrintStream ps = new PrintStream(console, true);
System.setOut(ps);
System.setErr(ps);
Scene app = new Scene(ta);
primaryStage.setScene(app);
primaryStage.show();
for (char c : "some text".toCharArray()) {
console.write(c);
}
ps.close();
}
public static void main(String[] args) {
launch(args);
}
public static class Console extends OutputStream {
private TextArea output;
public Console(TextArea ta) {
this.output = ta;
}
@Override
public void write(int i) throws IOException {
output.appendText(String.valueOf((char) i));
}
}
}
来源:https://stackoverflow.com/questions/13841884/redirecting-system-out-to-a-textarea-in-javafx