Javafx 2 JavaFX8中的日期选择器

Javafx 2 JavaFX8中的日期选择器,javafx-2,javafx,javafx-8,Javafx 2,Javafx,Javafx 8,在默认的JavaFX8包中是否有日期选择器和时间选择器的实现,我可以不使用第三方解决方案而使用它们?DatePicker 是的,Java 8有一个: 计时器选择器 不,Java8没有时间选择器 在()中有一个计时器选择器 考虑到Java 8已经有了一个日期选择器,添加一个时间选择器可能是一个合适的选择,如果您不想在弹出窗口中显示日历,您可以使用。。下面是一个使用内部CalendarPickerContent类的解决方案 DatePickerSkin skin = new DatePicker

在默认的JavaFX8包中是否有日期选择器和时间选择器的实现,我可以不使用第三方解决方案而使用它们?

DatePicker

是的,Java 8有一个:


计时器选择器

不,Java8没有时间选择器

在()中有一个计时器选择器


考虑到Java 8已经有了一个日期选择器,添加一个时间选择器可能是一个合适的选择,如果您不想在弹出窗口中显示日历,您可以使用。

。下面是一个使用内部CalendarPickerContent类的解决方案

DatePickerSkin skin = new DatePickerSkin(new DatePicker());
Node calendarControl = skin.getPopupContent();

以下是我基于@javaLearner答案的尝试:

DateTimePicker.java:

package test;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Skin;
import javafx.util.StringConverter;


public class DateTimePicker extends DatePicker{

    private ObjectProperty<LocalTime> timeValue = new SimpleObjectProperty<>();
    private ObjectProperty<ZonedDateTime> dateTimeValue;

    public DateTimePicker(){
        super();
        setValue(LocalDate.now());
        setTimeValue(LocalTime.now());
        setConverter(new StringConverter<LocalDate>() {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HH:mm:ssZ");
            @Override
            public String toString ( LocalDate object ) {               
                return dateTimeValue.get().format(formatter);
            }

            @Override
            public LocalDate fromString ( String string ) {
                return LocalDate.parse(string, formatter);
            }
        });
    }

    @Override
    protected Skin<?> createDefaultSkin () {
        return new DateTimePickerSkin(this);
    }

    public LocalTime getTimeValue(){
        return timeValue.get();
    }

    void setTimeValue(LocalTime timeValue){
        this.timeValue.set(timeValue);
    }

    public ObjectProperty<LocalTime> timeValueProperty(){
        return timeValue;
    }


    public ZonedDateTime getDateTimeValue() {
        return dateTimeValueProperty().get();
    }


    public void setDateTimeValue (ZonedDateTime dateTimeValue) {
        dateTimeValueProperty().set(dateTimeValue);
    }

    public ObjectProperty<ZonedDateTime> dateTimeValueProperty(){
        if (dateTimeValue == null){
            dateTimeValue = new SimpleObjectProperty<>(ZonedDateTime.of(LocalDateTime.of(this.getValue(), timeValue.get()), ZoneId.systemDefault()));
            timeValue.addListener(t -> {
                dateTimeValue.set(ZonedDateTime.of(LocalDateTime.of(this.getValue(), timeValue.get()), ZoneId.systemDefault()));
            });

            valueProperty().addListener(t -> {
                dateTimeValue.set(ZonedDateTime.of(LocalDateTime.of(this.getValue(), timeValue.get()), ZoneId.systemDefault()));
            });
        }
        return dateTimeValue;
    }


}
用法:

Main.java:

public class Main extends Application{

    @Override
    public void start ( Stage primaryStage ) {
        VBox vBox = new VBox();
        Scene s =  new Scene(new ScrollPane(vBox), 600, 400);
        DateTimePicker d = new DateTimePicker();

        // Date only
        d.valueProperty().addListener(t -> System.out.println(t));

        // Time only
        d.timeValueProperty().addListener(t -> System.out.println(t));

        // DateAndTime
        d.dateTimeValueProperty().addListener(t -> System.out.println(t));

        vBox.getChildren().add(d);

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

    public static void main ( String[] args ) {
        launch(args);
    }
}
仍然有StringConverter的工作要做,但即使这样,它还是非常有用的。希望它能帮助别人

PS:这是用jdk8u40测试的,它使用com.sun包(DatePickerContent/DatePickerSkin)中的类,这些类不是公共API,将来可能会更改,但很常见,即使更改了,修改上述代码有多困难!?:)


编辑:添加了iso8601格式的StringConverter,并添加了ZonedDateTime属性,以便更清晰地使用(如果不需要区域信息,可以与LocalDateTime交换)

时间选择器是否有任何选项?也许还有其他第三方解决方案?例如,我可以创建只接受时间值的自定义输入字段吗?看起来jfxtras有一个时间选择器,我从未使用过它。我在答案中添加了jfxtras时间选择器的链接。请投票:@jewelsea:我使用Jdk7和简单JavaFx,而不是lambda?那么解决方案是什么呢?我建议在Java8中使用DatePicker。如果您不能这样做,那么还有一个日期选择器,我相信它可以与Java7一起工作(尽管我从未尝试过它)。我不知道为什么它没有被提升!这为在短时间内实现一个好的datetimepicker提供了一个很好的开端。谢谢你举的这个例子。我更喜欢时间微调器,而不是滑块:
package test;

import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.HBox;

import com.sun.javafx.scene.control.skin.DatePickerContent;
import com.sun.javafx.scene.control.skin.DatePickerSkin;

public class DateTimePickerSkin extends DatePickerSkin {

    private DateTimePicker datePicker;
    private DatePickerContent ret;

    public DateTimePickerSkin(DateTimePicker datePicker){
        super(datePicker);
        this.datePicker = datePicker;
    }

    @Override 
    public Node getPopupContent() {
        if (ret == null){
            ret = (DatePickerContent) super.getPopupContent();

            Slider hours = new Slider(0, 23, (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getMinute() : 0));      
            Label hoursValue = new Label("Hours: " + (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getHour() : "") + " ");

            Slider minutes = new Slider(0, 59, (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getMinute() : 0));
            Label minutesValue =  new Label("Minutes: " + (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getMinute() : "") + " ");

            Slider seconds = new Slider(0, 59, (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getSecond() : 0));        
            Label secondsValue = new Label("Seconds: " + (datePicker.getTimeValue() != null ? datePicker.getTimeValue().getSecond() : "") + " ");

            ret.getChildren().addAll(new HBox(hoursValue, hours), new HBox(minutesValue, minutes), new HBox(secondsValue, seconds));

            hours.valueProperty().addListener((observable, oldValue, newValue) -> {
                datePicker.setTimeValue(datePicker.getTimeValue().withHour(newValue.intValue()));
                hoursValue.setText("Hours: " + String.format("%02d", datePicker.getTimeValue().getHour()) + " ");
            });

            minutes.valueProperty().addListener((observable, oldValue, newValue) -> {
                datePicker.setTimeValue(datePicker.getTimeValue().withMinute(newValue.intValue()));
                minutesValue.setText("Minutes: " + String.format("%02d", datePicker.getTimeValue().getMinute()) + " ");
            });

            seconds.valueProperty().addListener((observable, oldValue, newValue) -> {
                datePicker.setTimeValue(datePicker.getTimeValue().withSecond(newValue.intValue()));
                secondsValue.setText("Seconds: " + String.format("%02d", datePicker.getTimeValue().getSecond()) + " ");
            });

        }
        return ret;
    }


}
public class Main extends Application{

    @Override
    public void start ( Stage primaryStage ) {
        VBox vBox = new VBox();
        Scene s =  new Scene(new ScrollPane(vBox), 600, 400);
        DateTimePicker d = new DateTimePicker();

        // Date only
        d.valueProperty().addListener(t -> System.out.println(t));

        // Time only
        d.timeValueProperty().addListener(t -> System.out.println(t));

        // DateAndTime
        d.dateTimeValueProperty().addListener(t -> System.out.println(t));

        vBox.getChildren().add(d);

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

    public static void main ( String[] args ) {
        launch(args);
    }
}