JavaFX:将控制台输出重定向到在SceneBuilder中创建的TextArea [英] JavaFX: Redirect console output to TextArea that is created in SceneBuilder

查看:124
本文介绍了JavaFX:将控制台输出重定向到在SceneBuilder中创建的TextArea的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个简单的示例,应该可以让您了解当前发生的情况.

I've created a simple example that should give you an idea about what's happening right now.

现在发生的事情是,每当我单击按钮以将"HELLO WORLD"打印到TextArea时,程序将挂起并占用100%的CPU. Eclipse控制台面板中也没有输出.

What's happening right now is that whenever I click the button to print "HELLO WORLD" to the TextArea, the program will hang and use 100% of the CPU. There's also no output in the Eclipse console panel too.

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));
        }
    }
}


看来我的问题太长且难以理解.我正在重组这个.


EDIT 2: It seems that my question is way too long and hard to understand. I'm in the middle of restructuring this one.

我想我应该在这里展示所有内容.我想做的是为CLI应用程序提供一个简单的GUI前端.我是CS学生,Java是我们的主要语言,所以这主要是为了练习.

I guess I should just show everything here. What I'm trying to do is a simple GUI front-end for a CLI application. I'm a CS student and Java is our main language, so this is mainly for practice.

我一直在每个地方找几个小时,但是仍然没有解决方案.我已经尝试过像以前使用Swing一样做.该方法在Swing上效果很好,但在JavaFX上效果不好.

I've been looking every where for hours and hours but there's still no solution to this. I've tried doing the same like I did previously with Swing. The method worked fine with Swing but not with JavaFX.

这是我(当前)的logger.java类:

Here's my (current) logger.java Class:

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,但是它也不起作用.

I don't think there's any actual problems with this. I also did add the PrintStream object to redirect System.setOut and System.setErr in the MainController class to the TextArea, but it didn't work either.

我还有另一个Main类,这是加载FXML的主要内容.我尝试从那里重定向输出,它几乎可以正常工作.差不多了,因为我停止在Eclipse中看到控制台输出,而且我知道那是一个很大的进步.

I also have another Main class, which is the main thing that loads the FXML. I tried redirecting the output from there, it almost worked. Just almost, because i stopped seeing the console outputs inside Eclipse and I knew that was a great progress.

那么,这里似乎是什么问题?是因为FXML吗?我既是Java的绝对入门者,也是JavaFX的绝对入门者,这是我的第一个JavaFX应用程序.非常感谢任何指导.预先谢谢你.

So, what seems to be the problem here? Is it because of the FXML? I'm absolute beginner in Java and also JavaFX, this is my first JavaFX application. Any guidance is very much appreciated. Thank you in advance.

这是主班:

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);
    }
}

推荐答案

您正在使用console的值初始化ps,然后再由FXMLLoader对其进行初始化.即你有

You are initializing ps with the value of console before it has been initialized by the FXMLLoader. I.e you have

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

console传递给new Console(...)时,显然console仍然是null.

Clearly console is still null when you pass it to new Console(...).

FXMLLoader初始化注入的字段之后,您需要初始化ps,您可以使用initialize方法进行此操作.

You need to initialize ps after the FXMLLoader has initialized the injected fields, which you can do using the initialize method.

SSCCE:

MainController.java:

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:

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:

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>

这篇关于JavaFX:将控制台输出重定向到在SceneBuilder中创建的TextArea的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆