在JavaFX中创建和停止线程
我有一项任务要处理线程和JavaFX库。需要通过按下按钮启动单独的螺纹1。线程应该以较小的间隔(例如5毫秒)完成一个包含整数值(100-150)的列表 生成值后,它应该停止。新线程2必须启动并用生成的值填充视图列表 但每次线程1向列表中添加新值时,我都会遇到一个异常:在JavaFX中创建和停止线程,java,multithreading,javafx,task,Java,Multithreading,Javafx,Task,我有一项任务要处理线程和JavaFX库。需要通过按下按钮启动单独的螺纹1。线程应该以较小的间隔(例如5毫秒)完成一个包含整数值(100-150)的列表 生成值后,它应该停止。新线程2必须启动并用生成的值填充视图列表 但每次线程1向列表中添加新值时,我都会遇到一个异常: Exception in thread "Thread-4" java.lang.IllegalStateException: Not on FX application thread; currentThread = Threa
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元素
这是我的班级:
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);
}}`
int itemName=100;
按钮btnOne=新按钮(“按钮一”);
标签=新标签(“按下按钮开始”);
ObservalElist listOptions=FXCollections.ObservalArrayList();
列表视图列表;
@凌驾
public void start(Stage primaryStage)引发异常{
初级阶段。片名(“匆忙”);
列表=新列表视图(列表选项);
list.setPrefSize(120120);
多重选择模型=
list.getSelectionModel();
FlowPane根节点=新的FlowPane(10,10);
rootNode.setAlignment(位置中心);
scenemyscene=新场景(rootNode,180200);
初生阶段:集新世(myScene);
lvSelModel.selectedItemProperty().addListener(
(已更改、旧值、新值)->{
label.setText(“所选列表选项:”+newValue);
});
rootNode.getChildren().addAll(btnOne、list、label);
primaryStage.show();
Task threadOne=新任务(){
@凌驾
受保护的整数调用()引发异常{
while(itemName<130){
final int finalValue=itemName++;
add(String.valueOf(itemName));
Platform.runLater(
()->label.setText(“生成:“+finalValue”);
睡眠(100);
}
label.SETEXT(“螺纹1成品”);
返回itemName;
}
};
btnOne.setOnAction(
ae->{
螺纹th=新螺纹(螺纹一);
th.setDaemon(true);
th.start();
});
}
公共静态void main(字符串[]args){
发射(args);
}}`
结果程序应如下所示:
谢谢大家抽出时间 因为
listOptions
是列表视图中的项目列表,所以调用listOptions.add(…)
修改UI(列表视图)。因此,它需要在FX应用程序线程上执行,类似于设置标签的文本。只需将该行移到平台的一侧。稍后运行(…)
:
非常感谢。你帮了大忙!
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;
}
};
threadOne.setOnSucceeded(e -> {
// create another task and run it in another thread...
});