如何在 Java FXML 应用程序中初始化 DatePicker?
How do I initialize the DatePicker in a Java FXML app?
单击“添加约会”按钮时,会弹出新表单,但 DatePicker 为空(应该填充 LocalDate.now()),并且 Saturday/Sunday 日期中的 none 是禁用。尝试在 Initialize 和启动新场景的方法中调用设置方法。无论我将它放在一个或另一个或两个中,它都不起作用。请告知我做错了什么。谢谢。
图像显示 DatePicker 值空白且日历中没有禁用的日期。
package gci.controllers.dialogs;
import gci.App;
import gci.models.Appointment;
import gci.utilities.CustomerDAO;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.time.*;
import java.util.*;
import java.util.logging.*;
import java.util.stream.*;
import javafx.collections.*;
import javafx.event.ActionEvent;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.util.*;
public class AddAppointmentController implements Initializable {
@FXML private ChoiceBox<String> nameChoiceBox;
@FXML private ChoiceBox<String> typeChoiceBox;
@FXML private ChoiceBox<String> timeChoiceBox;
@FXML private Label titleLabel;
@FXML private Label copyrightLabel;
@FXML private Button saveButton;
@FXML private Button cancelButton;
@FXML private DatePicker datePicker;
private final CustomerDAO dao = new CustomerDAO();
private Stage stage;
private static final Region modal = new Region();
@Override
public void initialize(URL url, ResourceBundle rb) {
initApptChoiceBoxes();
setDatePicker();
setCopyright();
modal.setStyle("-fx-background-color: #00000099;");
}
private void initApptChoiceBoxes() {
try {
nameChoiceBox.setItems(dao.retrieveAll().stream().map(m -> m.getName())
.collect(Collectors.toCollection(FXCollections::observableArrayList)));
} catch (SQLException ex) {
Logger.getLogger(AddAppointmentController.class.getName()).log(Level.SEVERE, null, ex);
}
typeChoiceBox.setItems(FXCollections.observableArrayList("In-Person", "Phone", "WebMeeting"));
}
public void loadAddModifyAppointmentScene(Stage stage, Appointment appt) throws IOException {
Stage addAppointmentForm = new Stage();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(App.class.getResource("views/dialogs/add_appointment.fxml"));
Parent root = loader.load();
Parent parent = stage.getScene().getRoot();
StackPane stack = new StackPane(parent, modal);
modal.setVisible(true);
stage.setScene(new Scene(stack));
addAppointmentForm.setScene(new Scene(root));
addAppointmentForm.initModality(Modality.WINDOW_MODAL);
addAppointmentForm.initOwner(stage);
addAppointmentForm.initStyle(StageStyle.UNDECORATED);
AddAppointmentController controller = loader.getController();
controller.setStage(addAppointmentForm);
controller.setAppointment(appt);
controller.setDatePicker();
addAppointmentForm.show();
addAppointmentForm.centerOnScreen();
}
private void setStage(Stage stage) {
this.stage = stage;
}
private void setAppointment(Appointment appt) {
}
@FXML
private void handleCancelButton(ActionEvent event) {
this.stage.close();
modalOff();
}
@FXML
private void handleSaveButton(ActionEvent event) {
}
private void setCopyright() {
int year = LocalDate.now().getYear();
copyrightLabel.setText("Copyright © " + year + " Global Consulting Institution");
}
public void modalOff() {
modal.setVisible(false);
}
private void setDatePicker() {
datePicker = new DatePicker(LocalDate.now());
StringConverter<LocalDate> converter = datePicker.getConverter();
datePicker.setConverter(new StringConverter<LocalDate>() {
@Override
public String toString(LocalDate object) {
return converter.toString(object);
}
@Override
public LocalDate fromString(String string) {
LocalDate date = converter.fromString(string);
if (date.getDayOfWeek() == DayOfWeek.SATURDAY
|| date.getDayOfWeek() == DayOfWeek.SUNDAY) {
return datePicker.getValue();
} else {
return date;
}
}
});
datePicker.setDayCellFactory(d -> new DateCell() {
@Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
setDisable(empty || date.getDayOfWeek() == DayOfWeek.SATURDAY
|| date.getDayOfWeek() == DayOfWeek.SUNDAY);
}
});
datePicker.valueProperty().addListener((obs, ov, nv) -> {
if (nv.getDayOfWeek() == DayOfWeek.SATURDAY || nv.getDayOfWeek() == DayOfWeek.SUNDAY) {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Select Appointment");
alert.setHeaderText(null);
alert.setContentText("Business Hours are Mon - Fri, 8am - 5pm");
alert.showAndWait();
}
});
}
}
您在 setDatePicker()
中创建的 DatePicker
实例永远不会添加到场景中。它会覆盖加载 fxml 时由 FXMLLoader
注入的 DatePicker
对象(除非您没有正确添加 fx:id
)。在这个方法中完成的所有其他修改也在这个实例上完成。
您需要更换线路
datePicker = new DatePicker(LocalDate.now());
和
datePicker.setValue(LocalDate.now());
一般来说,您不应该为 @FXML
带注释的字段赋值。如果需要 "fix" a NullPointerException
或类似的东西,您只需解决症状而不是解决实际问题。此规则可能有例外,但您需要注意的是,您需要确保自己将节点添加到场景中。
单击“添加约会”按钮时,会弹出新表单,但 DatePicker 为空(应该填充 LocalDate.now()),并且 Saturday/Sunday 日期中的 none 是禁用。尝试在 Initialize 和启动新场景的方法中调用设置方法。无论我将它放在一个或另一个或两个中,它都不起作用。请告知我做错了什么。谢谢。
图像显示 DatePicker 值空白且日历中没有禁用的日期。
package gci.controllers.dialogs;
import gci.App;
import gci.models.Appointment;
import gci.utilities.CustomerDAO;
import java.io.IOException;
import java.net.URL;
import java.sql.SQLException;
import java.time.*;
import java.util.*;
import java.util.logging.*;
import java.util.stream.*;
import javafx.collections.*;
import javafx.event.ActionEvent;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
import javafx.util.*;
public class AddAppointmentController implements Initializable {
@FXML private ChoiceBox<String> nameChoiceBox;
@FXML private ChoiceBox<String> typeChoiceBox;
@FXML private ChoiceBox<String> timeChoiceBox;
@FXML private Label titleLabel;
@FXML private Label copyrightLabel;
@FXML private Button saveButton;
@FXML private Button cancelButton;
@FXML private DatePicker datePicker;
private final CustomerDAO dao = new CustomerDAO();
private Stage stage;
private static final Region modal = new Region();
@Override
public void initialize(URL url, ResourceBundle rb) {
initApptChoiceBoxes();
setDatePicker();
setCopyright();
modal.setStyle("-fx-background-color: #00000099;");
}
private void initApptChoiceBoxes() {
try {
nameChoiceBox.setItems(dao.retrieveAll().stream().map(m -> m.getName())
.collect(Collectors.toCollection(FXCollections::observableArrayList)));
} catch (SQLException ex) {
Logger.getLogger(AddAppointmentController.class.getName()).log(Level.SEVERE, null, ex);
}
typeChoiceBox.setItems(FXCollections.observableArrayList("In-Person", "Phone", "WebMeeting"));
}
public void loadAddModifyAppointmentScene(Stage stage, Appointment appt) throws IOException {
Stage addAppointmentForm = new Stage();
FXMLLoader loader = new FXMLLoader();
loader.setLocation(App.class.getResource("views/dialogs/add_appointment.fxml"));
Parent root = loader.load();
Parent parent = stage.getScene().getRoot();
StackPane stack = new StackPane(parent, modal);
modal.setVisible(true);
stage.setScene(new Scene(stack));
addAppointmentForm.setScene(new Scene(root));
addAppointmentForm.initModality(Modality.WINDOW_MODAL);
addAppointmentForm.initOwner(stage);
addAppointmentForm.initStyle(StageStyle.UNDECORATED);
AddAppointmentController controller = loader.getController();
controller.setStage(addAppointmentForm);
controller.setAppointment(appt);
controller.setDatePicker();
addAppointmentForm.show();
addAppointmentForm.centerOnScreen();
}
private void setStage(Stage stage) {
this.stage = stage;
}
private void setAppointment(Appointment appt) {
}
@FXML
private void handleCancelButton(ActionEvent event) {
this.stage.close();
modalOff();
}
@FXML
private void handleSaveButton(ActionEvent event) {
}
private void setCopyright() {
int year = LocalDate.now().getYear();
copyrightLabel.setText("Copyright © " + year + " Global Consulting Institution");
}
public void modalOff() {
modal.setVisible(false);
}
private void setDatePicker() {
datePicker = new DatePicker(LocalDate.now());
StringConverter<LocalDate> converter = datePicker.getConverter();
datePicker.setConverter(new StringConverter<LocalDate>() {
@Override
public String toString(LocalDate object) {
return converter.toString(object);
}
@Override
public LocalDate fromString(String string) {
LocalDate date = converter.fromString(string);
if (date.getDayOfWeek() == DayOfWeek.SATURDAY
|| date.getDayOfWeek() == DayOfWeek.SUNDAY) {
return datePicker.getValue();
} else {
return date;
}
}
});
datePicker.setDayCellFactory(d -> new DateCell() {
@Override
public void updateItem(LocalDate date, boolean empty) {
super.updateItem(date, empty);
setDisable(empty || date.getDayOfWeek() == DayOfWeek.SATURDAY
|| date.getDayOfWeek() == DayOfWeek.SUNDAY);
}
});
datePicker.valueProperty().addListener((obs, ov, nv) -> {
if (nv.getDayOfWeek() == DayOfWeek.SATURDAY || nv.getDayOfWeek() == DayOfWeek.SUNDAY) {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setTitle("Select Appointment");
alert.setHeaderText(null);
alert.setContentText("Business Hours are Mon - Fri, 8am - 5pm");
alert.showAndWait();
}
});
}
}
您在 setDatePicker()
中创建的 DatePicker
实例永远不会添加到场景中。它会覆盖加载 fxml 时由 FXMLLoader
注入的 DatePicker
对象(除非您没有正确添加 fx:id
)。在这个方法中完成的所有其他修改也在这个实例上完成。
您需要更换线路
datePicker = new DatePicker(LocalDate.now());
和
datePicker.setValue(LocalDate.now());
一般来说,您不应该为 @FXML
带注释的字段赋值。如果需要 "fix" a NullPointerException
或类似的东西,您只需解决症状而不是解决实际问题。此规则可能有例外,但您需要注意的是,您需要确保自己将节点添加到场景中。