在 Java 中,如何将一个 LocalDate 和一个时间格式的字符串连接到一个可观察的 属性 的 LocalDateTime 中?
In Java, how can I join a LocalDate and a time formatted String into one observable property of LocalDateTime?
我的尝试是将 DatePicker
(处理日期选择,但不处理时间)和 TextField
(处理时间)的值统一为可观察的 LocalDateTime
都加入了。
我已经在模型中为两者设置了可观察属性,但我很难加入它们。
到目前为止,我尝试了几次Bindings.createObjectBinding()
,但我似乎并没有取得太大的成功。
我至少想知道我是否走在正确的道路上,或者我应该采取不同的方式吗?
通过使用 LocalDateTime#of(LocalDate,LocalTime)
you can create a LocalDateTime
from a LocalDate
and a LocalTime
. What you need now is a way to get an instance of both a LocalDate
and a LocalTime
. Fortunately, the DatePicker
control gives you its value as a LocalDate
so we're done there. Next is finding a way to get a LocalTime
from a TextField
. This is possible by using a TextFormatter
and a StringConverter
which knows how to convert a String
to a LocalTime
and vice versa. There's a built-in StringConverter
for this use case: 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
的值将在文本为 "committed" 时更新(例如,在 TextField
具有焦点时按 Enter)。
我构建 LocalTimeStringConverter
的方式意味着它将使用我的 Locale
和 FormatStyle.SHORT
来解析和格式化 LocalTime
。例如,对我来说,这意味着 3:30 PM
或 11:25 AM
。这是可自定义的——请参阅 LocalTimeStringConverter
.
的各种构造函数
我的尝试是将 DatePicker
(处理日期选择,但不处理时间)和 TextField
(处理时间)的值统一为可观察的 LocalDateTime
都加入了。
我已经在模型中为两者设置了可观察属性,但我很难加入它们。
到目前为止,我尝试了几次Bindings.createObjectBinding()
,但我似乎并没有取得太大的成功。
我至少想知道我是否走在正确的道路上,或者我应该采取不同的方式吗?
通过使用 LocalDateTime#of(LocalDate,LocalTime)
you can create a LocalDateTime
from a LocalDate
and a LocalTime
. What you need now is a way to get an instance of both a LocalDate
and a LocalTime
. Fortunately, the DatePicker
control gives you its value as a LocalDate
so we're done there. Next is finding a way to get a LocalTime
from a TextField
. This is possible by using a TextFormatter
and a StringConverter
which knows how to convert a String
to a LocalTime
and vice versa. There's a built-in StringConverter
for this use case: 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
的值将在文本为 "committed" 时更新(例如,在 TextField
具有焦点时按 Enter)。
我构建 LocalTimeStringConverter
的方式意味着它将使用我的 Locale
和 FormatStyle.SHORT
来解析和格式化 LocalTime
。例如,对我来说,这意味着 3:30 PM
或 11:25 AM
。这是可自定义的——请参阅 LocalTimeStringConverter
.