gpt4 book ai didi

java - 如何正确处理 TextField 绑定(bind)并将节点引用与任务分开

转载 作者:行者123 更新时间:2023-12-02 02:52:42 25 4
gpt4 key购买 nike

我的问题适用于比 TextField 更广泛的节点,但我的示例仅包括这种特定类型的节点。

我的应用程序更改了 TextField 的内容,该 TextField 根据从 ChoiceBox 中选择的城市显示国家/地区名称:

My application changes the content of a TextField which displays the name of a country based on the selection of a city made from a ChoiceBox

我通过设置 countryTextField 的文本来实现此目的在 Task<Void>使用onAction选择框的事件处理程序:

@FXML
public void handleCityChoice() {
new Thread(new CityChoiceTask(cityChoiceBox.getValue())).start();
}

class CityChoiceTask extends Task<Void> {
String selection;
CityChoiceTask(String selection) {
this.selection = selection;
}
@Override
public Void call() {
Platform.runLater(() -> countryTextField.setText(Datasource.getInstance().
getCountryNameByCityName(selection)));
return null;
}
}

它工作得很好,但我真正想做的是将节点引用与 Task 完全分开。代码,因为这样做是最佳实践(我只是一名学生,所以如果我对此有误,请纠正我,但这就是我所学到的)。我尝试了以下操作,但继续抛出 NullPointerException ,我相信这是因为任务线程在执行绑定(bind)之前没有完成:

@FXML
public void handleCityChoice() {
Task task = new CityChoiceTask(cityChoiceBox.getValue());
new Thread(task).start();
countryTextField.textProperty().bind(task.valueProperty());
}

class CityChoiceTask extends Task<SimpleStringProperty> {
String selection;
CityChoiceTask(String selection) {
this.selection = selection;
}
@Override
public SimpleStringProperty call() {
String result = Datasource.getInstance().getCountryNameByCityName(selection));
return new SimpleStringProperty(result);
}
}

此外,System.out.println(task.valueProperty());

打印:

ObjectProperty [bean: controller.AddCustomer$CityChoiceTask@8b85d08, name: value, value: null]

线程没有及时执行确实是它抛出 NullPointerException 的原因吗? ,有办法解决吗?

顺便说一句,这种绑定(bind)在使用 TableView 时效果很好。例如,使用返回 ValueProperty 为 FXCollections.observableArrayList 的任务,类似于 myTableView.itemsProperty().bind(task);无论线程何时完成执行,都可以正常工作。

最佳答案

您需要使用正确的返回类型作为Task的类型参数。由于您要分配String属性,因此需要使用String。 (如果您不使用原始类型,您的编译器会提示此错误。)

@Override
public void start(Stage primaryStage) {
TextField text = new TextField();

Button btn = new Button("Run");
btn.setOnAction((ActionEvent event) -> {
Task<String> task = new Task<String>() {

@Override
protected String call() throws Exception {
Thread.sleep(1000);
return "Hello World";
}

};
text.textProperty().bind(task.valueProperty());
new Thread(task).start();
});

VBox root = new VBox(btn, text);

Scene scene = new Scene(root);

primaryStage.setScene(scene);
primaryStage.show();
}

您还可以使用 updateValue 方法发布中间更新。

<小时/>

另请注意,您的第一个代码片段实际上并未在非应用程序线程上执行任何工作。该任务仅用于调度稍后在应用程序线程上检索信息的代码。为此目的也不需要使用 Task 。一个简单的 Runnable 就足够了:

final String selection = cityChoiceBox.getValue();
new Thread(() -> {
// do this on this thread, not on the JavaFX application thread
final String result = Datasource.getInstance().getCountryNameByCityName(selection);

Platform.runLater(() -> countryTextField.setText(result));
}).start();

关于java - 如何正确处理 TextField 绑定(bind)并将节点引用与任务分开,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43562934/

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