Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
User interface 执行进程时更新TextArea_User Interface_Javafx_Concurrency_Updates_Fxml - Fatal编程技术网

User interface 执行进程时更新TextArea

User interface 执行进程时更新TextArea,user-interface,javafx,concurrency,updates,fxml,User Interface,Javafx,Concurrency,Updates,Fxml,当我点击“开始”按钮,如“无响应”时,我发现我的GUI在3-4秒后开始冻结。当我继续单击应用程序时,它将被迫关闭。 现在我想阻止这一切,但我不知道怎么做。就我所知,JavaFX在一个线程中运行,因此,要在方法执行时更新我的TextArea,我需要在另一个线程中运行这些方法。 我希望有人能帮助我 我的项目看起来怎么样? public class Handler { public void handle(List<String> files) { for (String s :

当我点击“开始”按钮,如“无响应”时,我发现我的GUI在3-4秒后开始冻结。当我继续单击应用程序时,它将被迫关闭。
现在我想阻止这一切,但我不知道怎么做。就我所知,JavaFX在一个线程中运行,因此,要在方法执行时更新我的TextArea,我需要在另一个线程中运行这些方法。
我希望有人能帮助我

我的项目看起来怎么样?

public class Handler {

public void handle(List<String> files) {
    for (String s : files) {
        List<String> ls = Reader.readFile(s);
        Writer.writeFile(Transformer.transform(ls));
    }
}
我得到了一个FXML、一个控制器、一个处理程序、一个转换器,还有一个Writer和一个Reader类(在处理程序类中使用)。
当我单击绑定到控制器中某个方法的按钮时,会创建一个Handler实例,该实例调用读取器读取文本文件,并转换为字符串列表(逐行)。
此外,这些线条正在被操纵。在此之后,将使用Writer创建一个新文件,并将新的操作行写入该文件。
还允许用户引用多个文件。
我想要的是,每当读卡器开始读取文件时,文本区域就会显示,如“正在读取文件”。
然后在Transformer开始工作时附加“文件…正在被操作”,然后
当新行写入新文件时,“文件…正在写入”

这里有一些代码。
控制器:

public class FXMLDocumentController implements Initializable {

@FXML
private TextArea console;

@FXML
private void handleButtonAction(ActionEvent event) {
    System.out.println("You clicked me!");
    Handler hand = new Handler();
    hand.handle(files);
}

@Override
public void initialize(URL url, ResourceBundle rb) {
    // TODO
}    

}
处理程序:

public class Handler {

public void handle(List<String> files) {
    for (String s : files) {
        List<String> ls = Reader.readFile(s);
        Writer.writeFile(Transformer.transform(ls));
    }
}
公共类处理程序{
公共无效句柄(列表文件){
用于(字符串s:文件){
List ls=Reader.readFile;
writeFile(Transformer.transform(ls));
}
}
每当读取、操作或写入文件时,我应该如何更改代码以更新文本区域

Info:我知道类处理程序不会编译,因为我删除了包含文件路径字符串的列表“files”的初始化

如果我遗漏了相关信息,请随时询问。

我提前感谢您!

您应该在后台线程中执行
handle()
方法:

@FXML
private void handleButtonAction(ActionEvent event) {
    System.out.println("You clicked me!");

    Thread thread = new Thread(() -> {
        Handler hand = new Handler();
        hand.handle(files);
    });

    // this line means the background thread will not prevent application exit:
    thread.setDaemon(true);

    thread.start();
}
如果要使用当前状态更新文本区域,则需要使用
Platform.runLater()
将其重新安排到FX应用程序线程上。最干净的方法可能是在
Handler
类中不使用
Platform.runLater()
,而是在
Handler
中定义一个用于“消费”的字段状态消息:

public class Handler {

    private final Consumer<String> statusMessageProcessor ;

    public Handler(Consumer<String> statusMessageProcessor) {
        this.statusMessageProcessor = statusMessageProcessor ;
    }

    // default processor does nothing:
    public Handler() {
        this(s -> {});
    }

    public void handle(List<String> files) {
        for (String s : files) {

            // similarly for other status updates:
            statusMessageProcessor.accept("The file "+s+" is being read");

            List<String> ls = Reader.readFile(s);
            Writer.writeFile(Transformer.transform(ls));
        }
    }
}
可以成为

Handler hand = new Handler(message -> 
    Platform.runLater(() -> console.appendText(message + "\n")));

在按钮处理程序方法中。

您应该在后台线程中执行
handle()
方法:

@FXML
private void handleButtonAction(ActionEvent event) {
    System.out.println("You clicked me!");

    Thread thread = new Thread(() -> {
        Handler hand = new Handler();
        hand.handle(files);
    });

    // this line means the background thread will not prevent application exit:
    thread.setDaemon(true);

    thread.start();
}
如果要使用当前状态更新文本区域,则需要使用
Platform.runLater()
将其重新安排到FX应用程序线程上。最干净的方法可能是在
Handler
类中不使用
Platform.runLater()
,而是在
Handler
中定义一个用于“消费”的字段状态消息:

public class Handler {

    private final Consumer<String> statusMessageProcessor ;

    public Handler(Consumer<String> statusMessageProcessor) {
        this.statusMessageProcessor = statusMessageProcessor ;
    }

    // default processor does nothing:
    public Handler() {
        this(s -> {});
    }

    public void handle(List<String> files) {
        for (String s : files) {

            // similarly for other status updates:
            statusMessageProcessor.accept("The file "+s+" is being read");

            List<String> ls = Reader.readFile(s);
            Writer.writeFile(Transformer.transform(ls));
        }
    }
}
可以成为

Handler hand = new Handler(message -> 
    Platform.runLater(() -> console.appendText(message + "\n")));

在按钮处理程序方法中。

您应该查看并发程序包中的任务和服务:。和。您应该查看并发程序包中的任务和服务:。和。我更喜欢第二种方式,否?因为我可以看到文件读取、操作和写入时的状态,而在处理程序中的第一个变体中看不到hand=newhandler(s->Platform.runLater(()->console.appendText(s+“\n”));是我的初始化列表吗?你是什么意思?这里只有一个解决方案。为了更容易理解,我将其分为两部分:第一,如何在后台线程中运行处理程序,第二,如何提供更新。
s
调用
处理程序
构造函数中的
只是lambda的参数名称(这就是传递给statusMessageProcessor.accept(…)
)的状态消息。您可以随意调用它(显然,如果您更改它,也可以在
控制台中更改它的使用。appendText(…)
)。谢谢!我删除了“Handler Handle=new Handler();”并复制了“Handler Handle=new Handler(s->Platform.runLater()->console.appendText(s+“\n”);“在线程声明之前,它现在可以正常工作了!并发是一个非常复杂的主题,我永远不知道应该使用什么实现(线程、任务、backgroundworker、使用者、服务等).你能给我一个链接或建议吗?有没有一种设计模式支持特殊情况下的线程实现?编辑:对不起,我缺少5个代表点,你能给我投票吗..请将答案标记为正确(你不需要声誉)如果它回答了问题。如果后台任务计算出您希望在UI中显示的结果(或者如果您希望在完成时更改UI),请使用
任务。您可以使用
任务
来完成此任务,但对于您描述的用法,简单的可运行没有什么好处。如果您希望能够多次重新启动任务,请使用
服务
。我更喜欢第二种方式,不是吗?因为我可以看到在第一个v中看不到的文件读取、操作和写入时的状态Handler中的变量.s=新处理程序(s->Platform.runLater(()->console.appendText(s+“\n”));是我的初始化列表吗?你是什么意思?这里只有一个解决方案。为了更容易理解,我将其分为两部分:第一,如何在后台线程中运行处理程序,第二,如何提供更新。
s
调用
处理程序
构造函数中的
只是lambda的参数名称(这就是传递给statusMessageProcessor.accept(…)
)的状态消息。您可以随意调用它(显然,如果您更改它,也可以在
控制台中更改它的使用。appendText(…)
)。谢谢!我删除了“Handler Handle=new Handler();”并复制了“Handler Handle=new Handler(s->Platform.runLater()->console.appendText(s+“\n”));“在线程声明之前,它是w