Validation javafx:如何为javafx文本字段添加验证时间的venthandler

Validation javafx:如何为javafx文本字段添加验证时间的venthandler,validation,javafx,time,event-handling,user-input,Validation,Javafx,Time,Event Handling,User Input,我很难找到任何关于如何为textfield添加venthandler的指南,以便它从关键输入进行实时验证,只允许hh:mm时间格式。我发现这个表达式^([0-9]| 0[0-9]| 1[0-9]| 2[0-3]):[0-5][0-9]$,但不知道如何将它添加到事件处理程序中。 我还试图使用simpleDateFormat,但没有成功 编辑:我正在尝试制作这样的东西(这是用JFrame制作的): 现在,我使用JavaFX创建了main和piezimes.java。在产品类中,我定义了要创建的对象:

我很难找到任何关于如何为
textfield
添加venthandler的指南,以便它从关键输入进行实时验证,只允许
hh:mm
时间格式。我发现这个表达式
^([0-9]| 0[0-9]| 1[0-9]| 2[0-3]):[0-5][0-9]$
,但不知道如何将它添加到
事件处理程序中。
我还试图使用
simpleDateFormat
,但没有成功

编辑:我正在尝试制作这样的东西(这是用JFrame制作的):

现在,我使用JavaFX创建了main和piezimes.java。在产品类中,我定义了要创建的对象:

public class Piezimes {
private LocalDate datums;
private String laiks;
private String piezime;

public Piezimes(){
    this.datums = null;
    this.laiks = "";
    this.piezime = "";
}

public Piezimes (LocalDate datums, String laiks, String piezime ){
    this.datums = datums;
    this.laiks = laiks;
    this.piezime = piezime;
}

public LocalDate getDatums() {

    return datums;
}

public void setDatums(LocalDate datums) {

    this.datums = datums;
}

public String getLaiks() {

    return laiks;
}

public void setLaiks(String laiks) {
    this.laiks = laiks;
}

public String getPiezime() {

    return piezime;
}

public void setPiezime(String piezime) {

    this.piezime = piezime;
}
}

在main.java中,我创建了tableView,在最后我添加了一些按钮,在这里我调用
.getText
,这样我就可以进行用户输入了。只有在时间验证方面我才有问题。
我现在调用的向表中添加用户输入的方法是:
piezimes.setLaiks(laiksIevade.getText())

老实说,我对TextFormatter不是很熟悉。每次我想做类似的事情时,我都在做一个自定义的TextField,在其中我向textProperty添加一个changeListener,并检查用户的输入是否与正则表达式匹配。现在,在您的情况下,您需要在focusedProperty中至少再添加一个,以检查用户是否未完成输入,我建议再添加一个以捕获操作事件。现在我不是正则表达式的大师,所以请宽容xD。以下是我的实现:

class CustomField extends TextField {

        public CustomField() {
            super();
            textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    if (newValue.isEmpty())
                        return;

                    if (newValue.matches("\\d{1,2}|\\d{1,2}:|\\d{1,2}:[0-5]?[0-9]")) {
                        setText(newValue);
                    } else {
                        setText(oldValue);
                    }
                }
            });

            setOnAction(e -> {
                if (!getText().matches("\\d{2}:\\d{2}")) {
                    setText("");
                }
            });

            focusedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue,
                        Boolean newPropertyValue) {
                    if (!newPropertyValue) {
                        if (!getText().matches("\\d{2}:\\d{2}")) {
                            setText("");
                        }
                    }
                }
            });
        }
    }
类CustomField扩展了TextField{
公共自定义字段(){
超级();
textProperty().addListener(新的ChangeListener()){
@凌驾

更改公众假期(ObservalEvalue@James_D尝试了这两种方法。对我的程序不起作用…你应该重写你的问题以显示你尝试了什么,并解释它以什么方式不起作用。提供一个。链接的问题提供了正确的方法。只是想知道你在swing应用程序中做了什么并不能阻止用户用鼠标粘贴无效文本(右键单击、粘贴等)?您在链接问题中尝试解决方案的代码在哪里?@James_uu。我在创建
textfield
后立即添加了验证。因此代码是这样的。
laiksIevade.textProperty().addListener(new ChangeListener(){…
。然后我刚刚调用了
piezimes.setLaiks(laiksIevade.getText());
来获取用户输入并完成操作。我想我完全错了。我不想问一个愚蠢的问题,但我的
textField
如何准确地调用它?我创建了类和新对象,即
CustomField c1=new CustomField()
。但是下一步该怎么办呢?。对编程来说真的很新,顺便说一句……没什么:P只需将c1节点添加到stage,它将只接受您所需格式的输入(如果我理解您的ofc正确)好的,我发现了一个问题。我是个白痴。我一直在我的void方法中调用validation,但没有在
void start
中调用。这就是为什么每次我尝试放入任何文本验证时,它都不起作用。现在它工作得非常好。顺便说一句,非常感谢您的回答。这种方法的一个问题是,您观察到对如果文本无效,则返回文本并还原它们。如果文本属性上有其他侦听器,则在看到有效状态之前,它们也会看到无效状态。因此,任何其他侦听器都必须知道如何检查文本的有效状态(如果无效,则可能忽略它)“
TextFormatter
通过在文本更改发生之前有效地否决文本更改来避免这种情况。它还有一个
value
属性,其中包含用户提交的值,该值可以是任何类型,您可以实现所需的任何解析逻辑。是的,我知道如果您不忽略Invalid输入,您可以轻松处理,但老实说,我不知道TextFormatter的功能。我将立即检查它。
class CustomField extends TextField {

        public CustomField() {
            super();
            textProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    if (newValue.isEmpty())
                        return;

                    if (newValue.matches("\\d{1,2}|\\d{1,2}:|\\d{1,2}:[0-5]?[0-9]")) {
                        setText(newValue);
                    } else {
                        setText(oldValue);
                    }
                }
            });

            setOnAction(e -> {
                if (!getText().matches("\\d{2}:\\d{2}")) {
                    setText("");
                }
            });

            focusedProperty().addListener(new ChangeListener<Boolean>() {
                @Override
                public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue,
                        Boolean newPropertyValue) {
                    if (!newPropertyValue) {
                        if (!getText().matches("\\d{2}:\\d{2}")) {
                            setText("");
                        }
                    }
                }
            });
        }
    }