JavaFX-TextArea实时输出

JavaFX-TextArea实时输出

一、不推荐使用JavaFx

Java 是好文明,而awt、swing,甚至JavaFx……

注意,如果你还未学过JavaFx相关,仅仅是想做桌面端程序的图形界面,极度不建议使用JavaFx!快去另寻出路吧!!!
注:桌面端推荐C#的WPF。

为什么这么说呢?用一个梗解释就是——
Java开发GUI?狗都不干!

至于具体原因,下面的话供大家参考。

【第一位的话】
很少有人用java开发界面,如果用也是netbean(国外多一点)。
GUI一般都用的vc和c#开发,java一般写b/s网页结构的程序。

【第二位的话】
硬要java做客户端程序,只有使用SWING库了。不过我觉得很丑。
PC客户端不会用java来做的,没人会在装软件的时候,再让客户装一个JRE。客户端都是C/C++。
Java的王道在于在网络编程、数据库编程。
java有成熟而且统一、强大的类库,开发起来相当方便。

【笔者的话】
现在的主流开发是网页开发(例如Java后端+Vue前端),在此基础上则是配套的移动端APP(Android/iOS)。b站就是最典型的例子。
而且对于jdk11及更高的版本,由于jdk中已经不再自带jfx,所以还需要自己下载相应内容并配置全局变量,较为麻烦。
最重要的是,如果你使用jfx遇到了问题,很难在网上找到相关解决方案,因为国内用jfx的人实在是太少太少了。
笔者是建议转WPF的,因为c#本身是面向对象,跟java语法结构基本一致,学习很容易;而且WPF也跟jfx类似,不能说不像,只能说完全一样。

如果你看到这里依然想了解JavaFx,那就看下去吧。

二、TextArea输出问题的背景

大家都肯定安装过很多应用,大部分应用安装的时候都会有安装进度窗口。有些比较简约的只有一个进度条,还有一些是可以看到当前的文件的详细处理情况。对于后者,如何做到处理的过程中就能让显示的窗口刷新信息呢?

在代码逻辑处理部分(相当于软件安装的安装逻辑)较为复杂,耗时过长的情况下,如果在处理的过程中给TextArea增加一行文本,该文本并不会立刻显示,而是在逻辑部分处理结束后,内容才一口气全部输出到TextArea中。

这显然不是我们想要的效果。预想效果应该是如同软件安装进度显示那样,在界面a确认后,跳转到界面b,并且自动开始处理;同时,TextArea可以像控制台程序一样,一行行及时输出。

三、原因及解决办法

很显然,这是一个UI刷新的问题。查阅资料后,发现了原因:
swing主线程必须结束返回,才将内容刷新到TextArea中。

解决方法也很容易:
在新的线程中对TextArea进行操作即可。

【笔者的碎碎念】
现在距离我当初写这篇文章时间已经过了很久了。现在想想,其实只要接触过UI的,基本都知道UI刷新应该新开线程循环,而非在主线程中直接操作。所以这个解决方案大概只有跟我一样小白的人才会看吧(

四、具体代码

说明:代码框架基于这位老哥的 JavaFX 登录界面跳转
下面只放出修改的地方
下面只放出修改的地方
下面只放出修改的地方
重要的事情说三遍。
请从上方链接下载基础代码,再按如下内容修改。

FXMLTest.java修改
    public void gotoMain() {
        try {
            MainController main = (MainController) replaceSceneContent("FXML_MAIN.fxml");
            main.setApp(this);
            // 新开三个线程,每个线程往TextArea不断输出指定字符串
            new PrintThread(main, "test1").start();
            new PrintThread(main, "test2").start();
            new PrintThread(main, "test3").start();
        } catch (Exception e) {
            Logger.getLogger(FXMLTest.class.getName()).log(Level.SEVERE, null, e);
        }
    }
MainController.java新增
    @FXML
    TextArea textArea;
FXML_MAIN.fxml修改

增加一个TextArea,并且将其fx:id设为textArea。

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

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

<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="500.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxmltest.MainController">
    <children>
        <Hyperlink layoutX="40.0" layoutY="254.0" onAction="#OUT_M" prefHeight="30.0" prefWidth="106.0" text="退出登录!" />
      <TextArea fx:id="textArea" layoutX="22.0" layoutY="24.0" prefHeight="215.0" prefWidth="457.0" />
    </children>
</AnchorPane>
新文件PrintThread.java
package fxmltest;

public class PrintThread extends Thread {
    
    private MainController main;
    private String s;

    PrintThread(MainController main, String s) {
        this.main = main;
        this.s = s;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
            // 注意,这里不属于swing主线程,所以appendText的内容才会被刷新
            main.textArea.appendText(s + "\n");
            try {
                sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

}

五、结尾

感谢你花费时间看到这里!希望本文能对你有所帮助。

一入jfx深似海,从此红尘是路人

立刻删除jfx,转战wpf

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个基本的JavaFX命令行终端的示例代码: ``` import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class CommandLineTerminal extends Application { private TextArea outputArea; @Override public void start(Stage primaryStage) throws Exception { outputArea = new TextArea(); outputArea.setEditable(false); TextField inputField = new TextField(); VBox root = new VBox(outputArea, inputField); Scene scene = new Scene(root, 400, 300); primaryStage.setScene(scene); primaryStage.show(); inputField.setOnAction(event -> { String command = inputField.getText(); inputField.clear(); outputArea.appendText("$ " + command + "\n"); executeCommand(command); }); } private void executeCommand(String command) { try { Process process = Runtime.getRuntime().exec(command); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { outputArea.appendText(line + "\n"); } } catch (IOException e) { outputArea.appendText("Error executing command: " + e.getMessage() + "\n"); } } public static void main(String[] args) { launch(args); } } ``` 该应用程序使用一个`VBox`布局来将一个`TextArea`和一个`TextField`垂直排列在一起。`TextArea`用于输出命令行的结果,而`TextField`用于接受用户的命令输入。 当用户在`TextField`中按下回车键时,应用程序将执行输入的命令,并将结果输出到`TextArea`中。在执行命令时,应用程序使用Java的`Runtime.getRuntime().exec()`方法来启动一个新的进程,并通过`BufferedReader`读取该进程的标准输出流。 此示例只是一个简单的终端模拟器,不具有完整的功能,例如支持多个命令和命令历史记录等。但它可以作为一个基础,用于构建更高级的终端应用程序。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值