JavaFX datepicker不更新值 [英] JavaFX datepicker not updating value

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

问题描述



我有一个datepicker控件,它是一个奇怪的,我正在使用JavaFX 8,我有一些奇怪的行为,我在Jubula测试期间。使用以下代码创建:

  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())
返回null;
返回LocalDate.parse(dateString,dateTimeFormatter );
}
});
dtpckr.setPromptText(yyyy / MM / dd);
dtpckr.setValue(LocalDate.parse(defaultDate.toString(),DateTimeFormatter.ofPattern(yyyy / MM / dd)));
return dtpckr;
}

正常工作,控件在表单上创建并按预期工作。如果我使用日历选择日期,则值将被更新。



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

  public void createSetDateAndTimeControls(){
DtDateAndTime currentDateAndTime;
try {
currentDateAndTime = systemstateController.getServerDateTime();
/ *
*创建要在窗体上使用的控件
* /
int width = 150;
DatePicker dtpckr = getDatePicker(currentDateAndTime.date,width);
标签lblDate = new Label(Date:);
标签lblTimeHour = new Label(Hour:);
标签lblTimeMinute = new Label(Minute:);
标签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);
/ *
*添加网格窗格以使控件保持正确的位置并正确对齐
* /
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);
/ *
*为用户创建按钮
* /
按钮bttnOK = new Button(更改日期和时间);
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(更新,日期和时间更新成功);
else
showErrorMessage(Error错误更新日期和时间);
}
else
showUserCancelledActionPopup();
} catch(ServerOfflineException | ServerNotBoundException e){
showExceptionErrorMessage(e);
}
}
});
bttnOK.setDefaultButton(true);
grdpn.add(bttnOK,2,5,3,1);
按钮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);
/ *
*在窗体上创建要使用的控件的结束
* /
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< 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())
返回null;
try {
return LocalDate .parse(dateString,dateTimeFormatter);
}
catch(异常e){
//输入错误的日期值
返回null;
}
}
});
dtpckr.setPromptText(yyyy / MM / dd);
dtpckr.setValue(LocalDate.parse(defaultDate.toString(),DateTimeFormatter.ofPattern(yyyy / MM / dd)));
//这里处理的位置在此处的缺陷值没有更新的焦点丢失
//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& ?扩展布尔> observable,Boolean oldValue,Boolean newValue){
if(!newValue){
dtpckr.setValue(dtpckr.getConverter()。fromString(dtpckr.getEditor()。getText())) ;
}
}
});
return dtpckr;
}


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.

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);
    }
}

Which has the following line:

bttnOK.setDefaultButton(true);

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.

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!

[Edit]

It appears this might be a bug in the current datepicker setup in JavaFX

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.setValue(datePicker.getConverter()
    .fromString(datePicker.getEditor().getText()));

So it's the datepicker.getEditor().getText() that holds the current text box details. I'm adding an event to the lost focus event, that will force the datepicker value to be updated

[Edit] And the working 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;
            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 datepicker不更新值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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