2013-07-11 47 views
6

將javafx Property的值保持在特定範圍內的最佳方法是什麼?限制哪些值可以在javafx屬性中解決?

(或 - 這是不好的做法,現有的任何理由從來沒有過濾由JavaFX的屬性包值?)

例1:避免負值在IntegerProperty
例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; 
     } 
    } 

只有扔在無效)的值超出範圍的異常(可保留屬性的值出界。

我是否忽略了提供用於過濾值的javafx屬性中的任何內容?

(如果必要的話,請幫我改善可能英文不好這個文本的...)

+1

在設置屬性之前驗證輸入可能會更簡單,例如驗證文本字段,數據庫結果或來自文件的數據。我看不出任何處理這個問題的好方法,你真的想要任何#set()調用來引發異常嗎? –

+0

你是真的:例如,設置列表的索引而無需訪問此列表是沒有意義的。但是如果我有權訪問列表,索引屬性的setter可能在列表中,並且屬性可能是隻讀的。在列表中,如果索引超出範圍,索引的setter可能會引發異常。 –

回答

2

在這兩個你的例子,似乎是順理成章的默認值(例如,如果它需要的是積極的,負數變爲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); 
    } 

有可能是那裏沒有邏輯默認值(或者你只是想拒絕無效值)的情況下,這情況使得它有點困難 - 你預期的要使用這樣的方法簽名,所以c阿列爾知道,如果值改變:

public boolean set(int value) 

爲了做到這一點,你必須回去好幾個班 - 所有回ReadOnlyIntegerProperty的方式,實現設置/自己無效結構。

我會毫不猶豫地使用Exceptions來處理無效輸入。這是對異常的合法使用,但是我擔心異常會被依賴於驗證。例外情況是非常耗費資源的,只有在需要修復的情況下才應該處理。所以這關係到你的意圖以及你相信使用你的班級做正確的事情的人(在發送給你之​​前進行驗證)。

+0

當然:如果輸入可能是非法的,我需要一個布爾函數來檢查輸入是否是非法的。這不包含在Javafx屬性中。 –

1

我相信我明白你現在更好地拍攝了什麼。您正在尋找執行用戶輸入驗證。

當你做你的用戶驗證,沒什麼兩種方法來解決:

  1. 驗證後,立即任何變化發生,並提供 反饋
  2. 驗證當焦點離開輸入區域

對於這兩者,您將使用屬性偵聽器 - 這只是您正在處理的屬性偵聽器的問題。

在第一種情況下,你會直接聽你驗證屬性:

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

在第二種情況下,你會聽focused財產,丟失焦點時驗證(你可以在這個監聽器維持最後的確認值,以幫助恢復如有必要)值:

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

注: 我是假設你只是希望把一個失敗的系統C安全更新UI。我會留下我以前的答案,因爲我相信它也提供了有用的信息。

+0

如果驗證返回false並將屬性恢復爲'oldValue',則驗證將以舊值重新啓動爲「新」。如果'oldValue'的驗證也返回false(也許在添加驗證偵聽器之前,屬性中包含的值),我們進入一個循環。在這種情況下,在恢復到oldValue之前也會更安全。 –

相關問題