Используя LocalDateTime#of(LocalDate,LocalTime)
, вы можете создать LocalDateTime
из LocalDate
и LocalTime
. Теперь вам нужен способ получить экземпляр как LocalDate
, так и LocalTime
. К счастью, элемент управления DatePicker
дает вам его значение как LocalDate
, так что мы закончили. Далее мы находим способ получить LocalTime
от TextField
. Это возможно с помощью TextFormatter
и StringConverter
, которые знают, как преобразовать String
в LocalTime
и наоборот. Для этого варианта использования есть встроенный StringConverter
: LocalTimeStringConverter
.
Как только у нас есть и DatePicker
, и TextFormatter
, нам нужно создать привязку, которая создаетLocalDateTime
из двух значений. Поскольку и DatePicker
, и TextFormatter
имеют свойство value
, которое содержит LocalDate
и, в этом случае, LocalTime
, соответственно, создание привязки относительно просто с Bindings#createObjectBinding(Callable,Observable...)
.
DatePicker dp = new DatePicker();
// Have to associate the TextFormatter with a TextField
TextFormatter<LocalTime> tf = new TextFormatter<>(new LocalTimeStringConverter());
ObjectBinding<LocalDateTime> binding = Bindings.createObjectBinding(() -> {
LocalDate ld = dp.getValue();
LocalTime lt = tf.getValue();
return ld == null || lt == null ? null : LocalDateTime.of(ld, lt);
}, dp.valueProperty(), tf.valueProperty());
Вот полный пример:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.converter.LocalTimeStringConverter;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class App extends Application {
@Override
public void start(Stage primaryStage) {
DatePicker datePicker = new DatePicker();
datePicker.setValue(LocalDate.now());
TextField timeField = new TextField();
TextFormatter<LocalTime> timeFieldFormatter =
new TextFormatter<>(new LocalTimeStringConverter());
timeField.setTextFormatter(timeFieldFormatter);
timeFieldFormatter.setValue(LocalTime.now());
HBox dateTimeBox = new HBox(10, datePicker, timeField);
dateTimeBox.setAlignment(Pos.CENTER);
ObjectBinding<LocalDateTime> ldtBinding = Bindings.createObjectBinding(() -> {
LocalDate date = datePicker.getValue();
LocalTime time = timeFieldFormatter.getValue();
return date == null || time == null ? null : LocalDateTime.of(date, time);
}, datePicker.valueProperty(), timeFieldFormatter.valueProperty());
Label ldtLabel = new Label();
ldtLabel.textProperty().bind(Bindings.createStringBinding(() -> {
LocalDateTime dateTime = ldtBinding.get();
return dateTime == null ? null : dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
}, ldtBinding));
VBox root = new VBox(15, dateTimeBox, ldtLabel);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(25));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
Вышеприведенное связывает текст Label
с ObjectBinding<LocalDateTime>
. Значение TextFormatter
будет обновляться всякий раз, когда текст «зафиксирован» (например, при нажатии , введите , когда TextField
имеет фокус).
То, как я сконструировал LocalTimeStringConverter
, означает, что он будет использовать мои Locale
и FormatStyle.SHORT
для анализа и форматирования LocalTime
. Например, для меня это означает что-то вроде 3:30 PM
или 11:25 AM
. Это настраивается - см. Различные конструкторы LocalTimeStringConverter
.