javafx:文本控件如何控制用户输入文本的格式

javafx:文本控件如何控制用户输入文本的格式

TextField里面有一个setTextFormatter()方法,需要传入javafx.scene.control.TextFormatter<V>类型

TextFormatter这个类通过使用两种不同的机制来描述文本框中文本的格式。对这两个机制学习之后我们可以做到控制、转化用户输入的文本。

  • 过滤器机制:可以拦截、修改用户的文本输入,不符合预设要求则可以拦截字符不予返回。

    ​ 由UnaryOperator<TextFormatter.Change>函数式接口提供支持

符合要求
不符合要求
用户输入
过滤器(filter)
文本显示
无反应
  • 值转换器机制:由StringConverter<V>接口提供支持。该接口有两个方法:

    public String toString(V value) 
    
    public T fromString(String s)
    

    转换器定义字符串和对象之间的转换行为。

    接下来是对这两个机制的详细介绍

UnaryOperator接口与TextFormatter过滤器

该接口只有一个方法,用户每次在文本框输入一个字符,TextFormatter都会调用该方法并将TextFormatter.Change对象作为参数传入

TextField textField = new Textfield();
textField.setTextFormatter(new TextFormatter<String>(new UnaryOperator<TextFormatter.Change>() {
            @Override
            public TextFormatter.Change apply(TextFormatter.Change change) {
                System.out.println(change.getText());
                return null;
            }
        }));

输入12345,控制台中,你看到的会类似于下面这样的输出。每输入一个字符都会产生一个Change对象

1
2
3
4
5

这里apply方法返回了null,实际运行之后会发现,输入任意字符,控制台能看见输入的字符,但是文本框没有任何显示。如果我们将null改为传入的change变量,那么文本就能正常显示了。这再次启示我们:我们完全可以借此过滤非法字符,只要在这个方法里进行if判断,非法字符则返回null就可以了。

使用lambda表达式重写会变得比较简洁

textField.setTextFormatter(new TextFormatter<String>(change -> {
    System.out.println(change.getText());
    return change;
}));

Change还有许多比较有意思的方法。除了返回每次文本框输入的新值getText()外,还有getControlNewText()方法,返回的是当前时刻控件里面所有的文本。有兴趣可以看文档

另外要注意的是,仍依次输入12345,我们有可能在控制台看见这样的输出

1


2


3


4


5


每一次输入新的字符,UnaryOperator接口竟然被调用了三次?!这个锅由中文输入法背。在中文输入法下,尤其是企图往框里输入中文,过滤器将会被很奇怪地调用。

StringConverter <T>值转换器与TextFormatter

先来看看TextFormatter的四个构造方法:

TextFormatter(StringConverter<V> valueConverter)

TextFormatter(StringConverter<V> valueConverter, V defaultValue)

TextFormatter(StringConverter<V> valueConverter, V defaultValue, UnaryOperator<TextFormatter.Change> filter)

TextFormatter(UnaryOperator<TextFormatter.Change> filter)

第四个很熟悉:其实就是使用指定的过滤器创建新的TextFormatter对象。

另外三个都与StringConverter 值转换器有关。

public StringConverter<V>() {
   public String toString(V value) 
 
   public T fromString(String s)
}

toString()fromString方法中,我们需要自定义一种类型的对象和文本框的文本(String)的对应关系。toString方法将对象以某种法则变成文本框里面的字符串(如果第一次启动程序,这将成为预设文本),fromString方法则根据用户的输入进行某些操作,并返回该类型的对象。

有几种时刻会调用这两个方法:

  • 窗口打开时,这个时候无论焦点在哪个控件,toString方法都会被调用。
  • 点击文本框(焦点移至文本框)时,toString方法会被调用。然后再点击其他控件(焦点从文本框离开时),fromString方法将会被调用。
  • 在选中文本框的情况下按下Enter键会调用fromString方法,这并不影响焦点离开文本框后调用fromString方法

当焦点再次移向这个文本框时,会发现,toString方法会再次被调用,传入的对象则是上一次fromString返回的对象。这是因为TextFormatter在私有域中保存了这个对象,以ObjectProperty<V>的形式。事实上,toString方法传入的也是这个对象。第二个第三个构造方法的V defaultValue,实际上是给这个域设置了一个初始值。

如果我们写一个从String到String的映射呢?

TextField textField = new Textfield();
textField.setTextFormatter(new TextFormatter<>(new StringConverter<String>() {
            @Override
            public String toString(String s) {
                System.out.println("start:" + s);
                if (s == null) {
                    return "Sorry, I am Null.";
                }
                return s;
            }

            @Override
            public String fromString(String s) {
                System.out.println("finish:" +s);
                return "I will come back.";
            }
        }));

来回移动焦点,控制台输出为

start:null
start:null
finish:Sorry, I am Null.
start:I will come back.
start:I will come back.
finish:I will come back.
start:I will come back.
finish:I will come back.

而且,无论用户输入了什么,焦点离开这个文本框的时候,都会重置回这句话“I will come back.”

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值