JavaFX datepicker没有更新值

有点奇怪,我正在使用JavaFX 8,并且我在Jubula测试期间遇到了一些奇怪的行为。

我有一个使用以下代码创建的datepicker控件:

public DatePicker getDatePicker(DtDate defaultDate, int width){ DatePicker dtpckr = new DatePicker(); dtpckr.setMaxWidth(width); dtpckr.setMinWidth(width); dtpckr.setConverter(new StringConverter() { 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; } 

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

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

 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() { @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() { @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事件,我并不特别想要。

所以问题是,如果用户在框中输入文本然后离开框而不按Enter键,为什么dtpckr.getValue()不会改变? 我找不到一个事件来调用用户离开datepicker框或者datepicker的属性来获取控件的文本值,并将其与dtpckr.getValue()的值进行比较。 这里有什么我想念的吗?

如果您需要更多信息,请与我们联系!

[编辑]

看起来这可能是JavaFX中当前datepicker设置中的一个错误

我可能必须删除默认按钮并在Jubula测试中输入回车按钮才能使其正常工作。 除非有人有替代方案?

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

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

所以它是datepicker.getEditor().getText() ,它保存当前文本框的详细信息。 我正在向丢失的焦点事件添加一个事件,这将强制更新datepicker值

[编辑]和工作代码:

 public DatePicker getDatePicker(DtDate defaultDate, int width){ DatePicker dtpckr = new DatePicker(); dtpckr.setMaxWidth(width); dtpckr.setMinWidth(width); dtpckr.setConverter(new StringConverter() { 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() { @Override public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { if (!newValue){ dtpckr.setValue(dtpckr.getConverter().fromString(dtpckr.getEditor().getText())); } } }); return dtpckr; } 

我有同样的问题。 有这个技巧来解决它:

 Date date = DateConverter.toDate(datePicker.getEditor().getText()); 

其中DateConverter.toDate()是将字符串转换为日期的方法。