JavaFX 日期选择器不更新值 [英] JavaFX datepicker not updating value

查看:21
本文介绍了JavaFX 日期选择器不更新值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有点奇怪,我使用的是 JavaFX 8,并且在 Jubula 测试期间发现了一些奇怪的行为.

Bit of an odd one, I'm using JavaFX 8 and am having some odd behaviour I picked up during my Jubula testing.

我有一个使用以下代码创建的日期选择器控件:

I have a datepicker control that is created with the following code:

public DatePicker getDatePicker(DtDate defaultDate, int width){
    DatePicker dtpckr = new DatePicker();
    dtpckr.setMaxWidth(width);
    dtpckr.setMinWidth(width);
    dtpckr.setConverter(new StringConverter<LocalDate>() {
        private DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy/MM/dd");
        @Override
        public String toString(LocalDate localDate) {
            if(localDate==null)
                return "";
            return dateTimeFormatter.format(localDate);
        }
        @Override
        public LocalDate fromString(String dateString) {
            if(dateString==null || dateString.trim().isEmpty())
                return null;
            return LocalDate.parse(dateString,dateTimeFormatter);
        }
    });
    dtpckr.setPromptText("yyyy/MM/dd");
    dtpckr.setValue(LocalDate.parse(defaultDate.toString(), DateTimeFormatter.ofPattern("yyyy/MM/dd")));
    return dtpckr;
}

这工作正常,控件在表单上创建并按预期工作.如果我使用日历来选择日期,则会更新该值.

That works fine and the control is created on the form and works as expected. If I use the calendar to pick the date, the value is updated.

现在,对于奇怪的部分,如果我输入日期选择器并手动输入日期(例如 2017/10/11),然后通过制表符或单击表单上的下一个文本框退出控件,日期选择器localdate 值不会更新.更新日期的唯一方法是按 Enter 键强制日期选择器实现新值的存在.这会导致另一个问题,因为我有以下代码:

Now, for the odd part, if I enter in the datepicker and manually type the date in (E.g. 2017/10/11) and then exit the control by either tabbing or clicking on the next textbox on the form, the datepicker localdate value doesn't get updated. The only method to update the date would be to press enter to force the datepicker to realise a new value is present. This causes another problem as I have the following code:

public void createSetDateAndTimeControls(){
    DtDateAndTime currentDateAndTime;
    try {
        currentDateAndTime = systemstateController.getServerDateTime();
        /*
         * Creating controls to be used on the form
         */
        int width = 150;
        DatePicker dtpckr = getDatePicker(currentDateAndTime.date, width);
        Label lblDate = new Label("Date:");
        Label lblTimeHour = new Label("Hour:");
        Label lblTimeMinute = new Label("Minute:");
        Label lblTimeSecond = new Label("Second:");
        TextField txtfldCurrentSetSecond = new TextField();
        TextField txtfldCurrentSetMinute = new TextField();
        TextField txtfldCurrentSetHour = new TextField();
        Slider sldrHourPicker = getSlider(width, SliderType.Hour, txtfldCurrentSetHour, currentDateAndTime.time);
        Slider sldrMinutePicker = getSlider(width, SliderType.Minute, txtfldCurrentSetMinute, currentDateAndTime.time);
        Slider sldrSecondPicker = getSlider(width, SliderType.Second, txtfldCurrentSetSecond, currentDateAndTime.time);
        /*
         * Adding a grid pane to keep controls in correct place and aligned correctly
         */
        GridPane grdpn = new GridPane();
        grdpn.add(lblDate, 1, 1);
        grdpn.add(dtpckr, 2, 1, 2,1);
        grdpn.add(lblTimeHour, 1, 2);
        grdpn.add(sldrHourPicker, 2, 2, 2 ,1);
        grdpn.add(txtfldCurrentSetHour, 4, 2);
        grdpn.add(lblTimeMinute, 1, 3);
        grdpn.add(sldrMinutePicker, 2, 3, 2, 1);
        grdpn.add(txtfldCurrentSetMinute, 4, 3);
        grdpn.add(lblTimeSecond, 1, 4);
        grdpn.add(sldrSecondPicker, 2, 4, 2, 1);
        grdpn.add(txtfldCurrentSetSecond, 4, 4);
        /*
         * Creating buttons for user to press
         */
        Button bttnOK = new Button("Change date and time");
        bttnOK.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                try {
                    if (checkIfAllDialogHasBeenFilledIn(grdpn)){
                        LocalDate test = dtpckr.getValue();
                        if (systemstateController.oeSetClock(ICrashUtils.setDateAndTime(dtpckr.getValue().getYear(), dtpckr.getValue().getMonthValue(), dtpckr.getValue().getDayOfMonth(),
                                (int)Math.floor(sldrHourPicker.getValue()), (int)Math.floor(sldrMinutePicker.getValue()), (int)Math.floor(sldrSecondPicker.getValue()))).getValue())
                            showOKMessage("Updated", "Date and time was updated successfully");
                        else
                            showErrorMessage("Error", "There was an error updating the date and time");
                    }
                    else
                        showUserCancelledActionPopup();
                } catch (ServerOfflineException | ServerNotBoundException e) {
                    showExceptionErrorMessage(e);
                }
            }
        });
        bttnOK.setDefaultButton(true);
        grdpn.add(bttnOK, 2, 5, 3, 1);
        Button bttnSetNow = new Button("Now");
        bttnSetNow.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                dtpckr.setValue(LocalDate.now());
                LocalTime time = LocalTime.now();
                sldrHourPicker.setValue(time.getHour());
                sldrMinutePicker.setValue(time.getMinute());
                sldrSecondPicker.setValue(time.getSecond());
            }
        });

        grdpn.add(bttnSetNow, 4, 1);
        /*
         * End of creating controls to be used on the form
         */
        anchrpnActivator.getChildren().add(grdpn);
        AnchorPane.setTopAnchor(grdpn, 0.0);
        AnchorPane.setRightAnchor(grdpn, 0.0);
        AnchorPane.setLeftAnchor(grdpn, 0.0);
        AnchorPane.setBottomAnchor(grdpn, 0.0);
    } catch (ServerOfflineException | ServerNotBoundException e) {
        showExceptionErrorMessage(e);
    }
}

其中有以下几行:

bttnOK.setDefaultButton(true);

这意味着如果用户在日期选择器控件上输入文本期间按下 Enter 键,它会在用户将数据放入其他控件之前触发 onaction 事件,而我不不是特别想要.

This means that if a user presses enter during the text entry on the date picker control, it fires off the onaction event, before the user has put in data in the other controls, and I don't particularly want that.

那么问题是,如果用户在框中输入文本然后不按 Enter 键就离开了框,为什么 dtpckr.getValue() 不会改变?我找不到一个事件来调用用户离开日期选择器框或日期选择器的属性来获取控件的文本值并将其与 dtpckr.getValue() 的值进行比较.有什么我在这里遗漏的吗?

So the question is, why doesn't the dtpckr.getValue() change if a user enters text into the box and then leaves the box without pressing enter? I can't find an event to call on user leaving the datepicker box or a property of the datepicker to get the text value of the control and compare it to the value of dtpckr.getValue(). Is there something that I'm missing here?

如果您需要更多信息,请告诉我!

Let me know if you need more information!

看来这可能是 JavaFX 中当前日期选择器设置中的一个错误

我可能必须删除默认按钮并在 Jubula 测试中按下回车键才能使其正常工作.除非有人有其他选择?

I might have to remove the default button and put in an enter press in the Jubula test to make this work properly. Unless someone has an alternative?

推荐答案

我在上面添加的错误日志有答案.您可以通过以下代码访问文本框的字符串值:

The bug log that I added above had the answer. You can access the string value of the textbox via this code:

datePicker.getEditor().getText();

因此可以通过以下方式设置文本框值:

So setting the textbox value can be done via:

datePicker.setValue(datePicker.getConverter()
    .fromString(datePicker.getEditor().getText()));

我正在向失去焦点事件添加一个事件,这将强制更新日期选择器值

I'm adding an event to the lost focus event, that will force the datepicker value to be updated

和工作代码:

public DatePicker getDatePicker(DtDate defaultDate, int width){
    DatePicker dtpckr = new DatePicker();
    dtpckr.setMaxWidth(width);
    dtpckr.setMinWidth(width);
    dtpckr.setConverter(new StringConverter<LocalDate>() {
        private DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy/MM/dd");
        @Override
        public String toString(LocalDate localDate) {
            if(localDate==null)
                return "";
            return dateTimeFormatter.format(localDate);
        }
        @Override
        public LocalDate fromString(String dateString) {
            if(dateString==null || dateString.trim().isEmpty())
                return null;
            try{
                return LocalDate.parse(dateString,dateTimeFormatter);
            }
            catch(Exception e){
                //Bad date value entered
                return null;
            }
        }
    });
    dtpckr.setPromptText("yyyy/MM/dd");
    dtpckr.setValue(LocalDate.parse(defaultDate.toString(), DateTimeFormatter.ofPattern("yyyy/MM/dd")));
    //This deals with the bug located here where the datepicker value is not updated on focus lost
    //https://bugs.openjdk.java.net/browse/JDK-8092295?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
    dtpckr.focusedProperty().addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            if (!newValue){
                dtpckr.setValue(dtpckr.getConverter().fromString(dtpckr.getEditor().getText()));
            }
        }
    });
    return dtpckr;
}

这篇关于JavaFX 日期选择器不更新值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆