首页 > 解决方案 > JavaFX Concurrency - Label 和 TextArea 之间的不同行为

问题描述

我对 JavaFX 和并发性很陌生。目前我正在努力更好地掌握它。

我了解 JavaFX 节点不是线程安全的,需要从应用程序 (UI) 线程进行更新。

在以下示例中,我使用该javafx.application runLater 方法更新标签,否则我将抛出异常。但另一方面,我可以从后台任务中更新 TextArea:

textArea.appendText(status+"\n");

你能帮我理解在这种情况下 Label 和 TextArea 之间的区别,以及为什么一个不能在 BG 任务中更新而另一个可以吗?

package test;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FxConcurrencyExample1  extends Application
{
    // Create the TextArea
    TextArea textArea = new TextArea();

    // Create the Label
    Label statusLabel = new Label("Not Started...");

    // Create the Buttons
    Button startButton = new Button("Start");
    Button exitButton = new Button("Exit");

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

    @Override
    public void start(final Stage stage) 
    {
        // Create the Event-Handlers for the Buttons
        startButton.setOnAction(new EventHandler <ActionEvent>() 
        {
            public void handle(ActionEvent event) 
            {
                startTask();
            }
        });

        exitButton.setOnAction(new EventHandler <ActionEvent>() 
        {
            public void handle(ActionEvent event) 
            {
                stage.close();
            }
        });

        // Create the ButtonBox     
        HBox buttonBox = new HBox(5, startButton, exitButton);

        // Create the VBox
        VBox root = new VBox(10, statusLabel, buttonBox, textArea);

        // Set the Style-properties of the VBox
        root.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-border-color: blue;");

        // Create the Scene
        Scene scene = new Scene(root,400,300);
        // Add the scene to the Stage
        stage.setScene(scene);
        // Set the title of the Stage
        stage.setTitle("A simple Concurrency Example");
        // Display the Stage
        stage.show();       
    }

    public void startTask() 
    {
        // Create a Runnable
        Runnable task = new Runnable()
        {
            public void run()
            {
                runTask();
            }
        };

        // Run the task in a background thread
        Thread backgroundThread = new Thread(task);
        // Terminate the running thread if the application exits
        backgroundThread.setDaemon(true);
        // Start the thread
        backgroundThread.start();
    }

    public void runTask() 
    {
        for(int i = 1; i <= 10; i++) 
        {
            try
            {
                String status = "Processing " + i + " of " + 10;
                System.out.println(status);
                // Update the Label on the JavaFx Application Thread        
                Platform.runLater(new Runnable() 
                {
                    @Override
                    public void run() 
                    {
                        statusLabel.setText(status);
                    }
                });
                textArea.appendText(status+"\n");
                Thread.sleep(1000);
            }
            catch (InterruptedException e) 
            {
                e.printStackTrace();
            }
        }
    }   
}

谢谢保罗

标签: javamultithreadingjavafx

解决方案


推荐阅读