JDK 1.8 (8u231)、Windows 10 出现以下问题
我有一个DatePicker带有侦听器的设置,该侦听器显示Alert值何时更改。但是,一旦Alert显示 ,就会datePicker.valueProperty()恢复到其原始值。
这似乎不是“按设计工作”,并且多个其他开发人员已确认该问题在更高版本的 Java 中不存在。
这是一个 MCVE 来演示:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.DatePicker;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class DatePickerCommit extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
DatePicker datePicker = new DatePicker();
// Add listener on DatePicker
datePicker.valueProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
// Show an Alert
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setContentText("You selected " + newValue);
alert.show();
alert.setY(alert.getY()+100);
}
});
root.getChildren().add(datePicker);
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sample");
primaryStage.show();
}
}
Run Code Online (Sandbox Code Playgroud)
在Alert本身不显示正确的日期,但DatePicker valueProperty()恢复到null,在这个截图所示:
使用 IntelliJ 的调试器,我可以在(或) 调用后datePicker.valueProperty()立即确认设置为“空” 。alert.show()alert.showAndWait()
最近的潜在已知错误:
我能够找到一些似乎相关的已知错误,但它们都被标记为自 8u73 起已解决(可能是回归?):
我能够在我当前正在使用的 JDK 版本中重现此问题。因此,经过调查,根本原因是在将值提交给 textField 之前将焦点转移到新阶段(或从 DatePicker 失去焦点)。
在调试时我注意到以下结果:
选项#1: 以另一种方式采用@Kleopatra 解决方案,即在显示警报之前设置文本。这样我们就欺骗了ComboBoxPopupControl -> setTextFromTextFieldIntoComboBoxValue 方法,让其认为 textField 中有一个有效值,而不让它重置该值。
选项#2: 将显示警报的部分包装在Platform.runLater中,以处理稍后执行时显示的警报(此时提交将已在 DatePicker 中执行)。
这适用于手动输入的日期和在弹出窗口中选择的日期。
不确定此解决方法是否适合您。你可以尝试一下吗?
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.DatePicker;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.time.LocalDate;
public class DatePickerCommit extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Simple Interface
VBox root = new VBox(10);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(10));
DatePicker datePicker = new DatePicker();
// Add listener on DatePicker
datePicker.valueProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null) {
// Option#1
datePicker.getEditor().setText(datePicker.getConverter().toString(newValue));
showAlert(newValue);
// Option#2
//Platform.runLater(()->showAlert(newValue));
}
});
root.getChildren().add(datePicker);
// Show the stage
primaryStage.setScene(new Scene(root));
primaryStage.setTitle("Sample");
primaryStage.show();
}
private void showAlert(LocalDate value){
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setContentText("You selected " + value);
alert.show();
alert.setY(alert.getY()+100);
}
}
Run Code Online (Sandbox Code Playgroud)