gpt4 book ai didi

java - 在 JavaFX 中创建和停止线程

转载 作者:行者123 更新时间:2023-11-30 03:08:37 28 4
gpt4 key购买 nike

我有一个使用线程和 JavaFX 库的任务。需要通过按下按钮来启动单独的线程 1。该线程应该以较小的间隔(例如 5 毫秒)完成一个包含整数值 (100 - 150) 的列表。

生成值后,它应该停止。新线程 2 必须启动并用生成的值填充 ViewList。

但是每次当线程 1 将新值添加到我的列表中时,我都会遇到异常:

Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-4
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:204)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:364)
at javafx.scene.Scene.addToDirtyList(Scene.java:485)
at javafx.scene.Node.addToSceneDirtyList(Node.java:424)
at javafx.scene.Node.impl_markDirty(Node.java:415)

我尝试在按钮事件监听器中使用 Platform.runLater() 而不是创建新线程,但在这种情况下程序停止响应。

任何人都可以帮助我,如何在单独的线程中用值填充集合以及如何在第一个线程完成后启动第二个线程来更新 ViewList 元素?

这是我的类(class):

int itemName = 100;
Button btnOne = new Button("Button one");
Label label = new Label("Press the button to start");

ObservableList<String> listOptions = FXCollections.observableArrayList();
ListView<String> list;

@Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Hurry");

list = new ListView<>(listOptions);
list.setPrefSize(120, 120);

MultipleSelectionModel<String> lvSelModel =
list.getSelectionModel();

FlowPane rootNode = new FlowPane(10, 10);
rootNode.setAlignment(Pos.CENTER);

Scene myScene = new Scene(rootNode, 180, 200);
primaryStage.setScene(myScene);

lvSelModel.selectedItemProperty().addListener(
(changed, oldValue, newValue) -> {
label.setText("List option selected: " + newValue);
});

rootNode.getChildren().addAll(btnOne, list, label);
primaryStage.show();

Task<Integer> threadOne = new Task<Integer>(){
@Override
protected Integer call() throws Exception{

while(itemName < 130){
final int finalValue = itemName++;
listOptions.add(String.valueOf(itemName));
Platform.runLater(
() -> label.setText("Generating: " + finalValue));
Thread.sleep(100);
}
label.setText("Thread 1 finished");
return itemName;
}
};

btnOne.setOnAction(
ae -> {
Thread th = new Thread(threadOne);
th.setDaemon(true);
th.start();
});

}

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

结果程序应该是这样的:

感谢大家的宝贵时间!

最佳答案

由于 listOptions 是 ListView 中的项目列表,因此调用 listOptions.add(...) 会修改 UI( ListView )。因此它需要在 FX 应用程序线程上执行,类似于设置标签的文本。只需将该行移到 Platform.runLater(...) 旁边即可:

Task<Integer> threadOne = new Task<Integer>(){
@Override
protected Integer call() throws Exception{

while(itemName < 130){
final int finalValue = itemName++;
Platform.runLater(() -> {
listOptions.add(String.valueOf(itemName));
label.setText("Generating: " + finalValue);
});
Thread.sleep(100);
}
label.setText("Thread 1 finished");
return itemName;
}
};

要在第一个任务完成时启动另一个任务(或者执行任何操作),请使用该任务的 onSucceeded 处理程序:

threadOne.setOnSucceeded(e -> {
// create another task and run it in another thread...
});

关于java - 在 JavaFX 中创建和停止线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34142797/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com