对于JavaFX和并发我还是很陌生。目前,我正在尝试更好地掌握它。
我了解到JavaFX节点不是线程安全的,因此需要从应用程序(UI)线程进行更新。
在下面的示例中,我正在使用javafx.application
runLater
方法来更新Label,否则我将抛出异常。
但另一方面,我可以从后台任务中更新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();
}
}
}
}
谢谢 保罗