限制哪些值可以在javafx属性中结算?

限制哪些值可以在javafx属性中结算?,java,properties,javafx,javafx-2,Java,Properties,Javafx,Javafx 2,将javafx属性的值保持在特定范围内的最佳方法是什么 (或者-这是一种不好的做法,有没有任何理由不过滤javafx属性包装的值?) 示例1:避免整数属性中出现负值 示例2:将IntegerProperty的值保持在列表的范围内 第一个想法:-覆盖IntegerPropertyBase.set(int)。安全吗?实际上setValue(int)只调用set(int),但是如果有一天这个实现发生了变化,那么对值集的控制就会丢失 第二个想法:-重写IntegerPropertyBase.invali

将javafx属性的值保持在特定范围内的最佳方法是什么

(或者-这是一种不好的做法,有没有任何理由不过滤javafx属性包装的值?)

示例1:避免整数属性中出现负值
示例2:将IntegerProperty的值保持在列表的范围内

第一个想法:-覆盖
IntegerPropertyBase.set(int)
。安全吗?实际上
setValue(int)
只调用
set(int)
,但是如果有一天这个实现发生了变化,那么对值集的控制就会丢失

第二个想法:-重写IntegerPropertyBase.invalidate()。但是在这一点上,这个值已经设置好了

它是否更适合javafx属性抛出一个
IllegalArgumentException
(或者
ArrayIndexOutOfBoundsException
,如果包装的值是数组的索引),或者更好地拒绝超出边界的值,设置边界中的最后一个值

也许是这样:

    class BoundedIntegerProperty extends IntegerPropertyBase {
        (...)
        int oldValue = defaultValueInBounds;
        boolean settingOldValue = false;
        public void invalidated() {
            if(!settingOldValue){
                if(outOfBounds(get())){
                    settingOldValue = true;
                    set(oldValue);
                } else {
                    oldValue = get();
                }
            } else
                settingOldValue = false;
        }
    }
只有在invalidated()中抛出值超出范围的异常,才能使属性的值超出范围

我是否忽略了提供给筛选值的javafx属性中的任何内容?


(如有必要,请帮助我改进本文中可能不好的英语…

在两个示例中,似乎都有一个逻辑默认值(例如,如果要求为正数,负数将变为0)。假设您记录的很好(如果值无效,默认值是什么),我认为您的第一种方法似乎走在了正确的道路上

我建议您从一个具体的类开始,比如要扩展的类
SimpleIntegerProperty
(除非您选择
IntegerPropertyBase

然后,我将覆盖
set(int)
方法和
setValue(Number)
方法,将父对象包装到您的逻辑中:

    /**
     * Explanation that values under 0 are set to 0
     */
    @Override
    public void set(int value){
        super.set(value > 0 ? value : 0);
    }

    /**
     * Explanation that values under 0 are set to 0
     */
    @Override
    public void setValue(Number value){
        super.setValue(value.intValue() > 0 ? value : 0);
    }
可能存在这样一种情况,即没有逻辑默认值(或者您只想拒绝无效值)。这种情况使问题变得更加困难—您实际上希望使用类似的方法签名,以便调用者知道值是否更改:

public boolean set(int value)
为了做到这一点,您必须返回许多类—一直返回到
ReadOnlyIntegerProperty
,并自己实现设置/失效结构


我会犹豫是否使用异常来处理无效的输入。这是对异常的合法使用,但我担心的是,异常会被依赖于验证。异常是非常资源密集型的,只有在有需要修复的事情时才应该被命中。所以这真的是关于你的意图以及你对peop的信任程度请使用您的类来做正确的事情(并在发送给您之前进行验证)。

我相信我了解您现在的目标。您希望执行用户输入验证

在进行用户验证时,实际上有两种方法:

  • 任何变更发生后立即验证,并提供 回馈
  • 验证焦点何时离开输入区域
  • 使用这两种方法,您将使用属性侦听器—这只是您正在处理的属性侦听器的问题

    在第一种情况下,您将直接侦听正在验证的属性:

        TextField field = new TextField();
        field.textProperty().addListener(new ChangeListener<String>(){
            @Override
            public void changed(ObservableValue<? extends String> value,
                    String oldValue, String newValue) {
                    //Do your validation or revert the value
            }});
    
    注意:
    我假设您只是想为更新UI的系统代码设置一个故障保护。我将保留我以前的回答,因为我相信它也提供了有用的信息。

    在设置属性之前验证输入可能更简单,例如验证文本字段、DB结果或文件中的数据。我看不到任何好的处理方法,w你真的想要一套吗调用以引发异常?您是对的:例如,为没有访问此列表权限的列表设置索引是没有意义的。但是,如果我有访问此列表的权限,则索引属性的设置器可能在列表本身中,并且该属性可能是只读的。在列表中,如果索引超出范围,则索引的设置器可能引发异常边界。当然:如果输入可能非法,我需要一个布尔函数来检查输入是否非法。这不包含在Javafx属性中。如果验证返回false,并且我将属性还原为
    oldValue
    ,则验证将以“new”的旧值重新开始。如果对
    oldValue
    的验证也返回false(可能是添加验证侦听器之前属性中包含的值),我们将进入一个循环。在这种情况下,在还原到它们之前验证
    oldValue
    会更安全。
        TextField field = new TextField();
        field.focusedProperty().addListener(new ChangeListener<Boolean>(){
            String lastValidatedValue = "";
            @Override
            public void changed(ObservableValue<? extends Boolean> value,
                    Boolean oldValue, Boolean newValue) {
                if(newValue == false && oldValue == true){
                    //Do your validation and set `lastValidatedValue` if valid
                }
            }});