2012-11-16 39 views
5

मैंने टेक्स्टफिल्ड सत्यापन के अपने पिछले कार्यान्वयन में सुधार किया, इस बार बाध्यकारी का उपयोग करके वास्तविक समय सत्यापन के साथ एक वास्तविक कस्टम नियंत्रण बना रहा। यह अधिक जावा कोड की आवश्यकता के बिना FXML के साथ प्रयोग योग्य है।जावाएफएक्स 2.2 एफएक्सएमएल मान्य टेक्स्टफिल्ड

import javafx.beans.binding.BooleanBinding; 
import javafx.beans.property.BooleanProperty; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.ReadOnlyBooleanProperty; 
import javafx.beans.property.ReadOnlyIntegerProperty; 
import javafx.beans.property.ReadOnlyStringProperty; 
import javafx.beans.property.SimpleBooleanProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.control.TextField; 
import javafx.scene.effect.BlurType; 
import javafx.scene.effect.DropShadow; 
import javafx.scene.effect.Effect; 
import javafx.scene.paint.Color; 

/** 
* <p> 
* TextField with regex-based real-time input validation. 
* JavaFX 2 and FXML compatible. </p> 
* <p> 
* FXML code example:<div> 
* {@code <ValidatedTextField fx:id="validatedTextField" minLength="1" maxLength="1" mask="^[0-9]*$" />} 
* </div> 
* </p> 
* 
* @author 82300009 
*/ 
public final class ValidatedTextField extends TextField { 

    private final BooleanProperty invalid = new SimpleBooleanProperty(false); 
    private final StringProperty mask; 
    private final IntegerProperty minLength; 
    private final IntegerProperty maxLength; 

    private Effect invalidEffect = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0); 

    public ValidatedTextField() { 
     super(); 
     this.mask = new SimpleStringProperty("."); 
     this.minLength = new SimpleIntegerProperty(-1); 
     this.maxLength = new SimpleIntegerProperty(-1); 

     bind(); 
    } 

    public ValidatedTextField(String mask, int minLength, int maxLength, boolean nullable) { 
     this(mask, minLength, maxLength, nullable, null); 
    } 

    public ValidatedTextField(String mask, int minLength, int maxLength, boolean nullable, String string) { 
     super(string); 
     this.mask = new SimpleStringProperty(mask); 
     this.minLength = new SimpleIntegerProperty(minLength); 
     this.maxLength = new SimpleIntegerProperty(maxLength); 

     bind(); 
    } 

    public ReadOnlyBooleanProperty invalidProperty() { 
     return invalid; 
    } 

    public ReadOnlyStringProperty maskProperty() { 
     return mask; 
    } 

    public ReadOnlyIntegerProperty minLengthProperty() { 
     return minLength; 
    } 

    public ReadOnlyIntegerProperty maxLengthProperty() { 
     return maxLength; 
    } 

    public boolean getInvalid() { 
     return invalid.get(); 
    } 

    public String getMask() { 
     return mask.get(); 
    } 

    public void setMask(String mask) { 
     this.mask.set(mask); 
    } 

    public int getMinLength() { 
     return minLength.get(); 
    } 

    public void setMinLength(int minLength) { 
     this.minLength.set(minLength); 
    } 

    public int getMaxLength() { 
     return maxLength.get(); 
    } 

    public void setMaxLength(int maxLength) { 
     this.maxLength.set(maxLength); 
    } 

    public Effect getInvalidEffect() { 
     return this.invalidEffect; 
    } 

    public void setInvalidEffect(Effect effect) { 
     this.invalidEffect = effect; 
    } 

    private void bind() { 
     this.invalid.bind(maskCheck().or(minLengthCheck())); 

     this.textProperty().addListener(new ChangeListener<String>() { 
      @Override 
      public void changed(ObservableValue<? extends String> ov, String t, String t1) { 
       if (textProperty().get().length() > maxLength.get()) { 
        setText(t); 
       } 
      } 
     }); 

     this.invalid.addListener(new ChangeListener<Boolean>() { 
      @Override 
      public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) { 
       if (t^t1) { 
        if (t1) { 
//      setStyle("-fx-font-weight: bold; -fx-text-fill: red;"); 
         setEffect(invalidEffect); 
        } else { 
//      setStyle("-fx-font-weight: normal; -fx-text-fill: inherit;"); 
         setEffect(null); 
        } 
       } 

      } 
     }); 
    } 

    private BooleanBinding maskCheck() { 
     return new BooleanBinding() { 
      { 
       super.bind(textProperty(), mask); 
      } 

      @Override 
      protected boolean computeValue() { 
       return !textProperty().get().matches(mask.get()); 
      } 
     }; 
    } 

    private BooleanBinding minLengthCheck() { 
     return new BooleanBinding() { 
      { 
       super.bind(textProperty(), minLength); 
      } 

      @Override 
      protected boolean computeValue() { 
       return textProperty().get().length() < minLength.get(); 
      } 
     }; 
    } 

    private BooleanBinding maxLengthCheck() { 
     return new BooleanBinding() { 
      { 
       super.bind(textProperty(), maxLength); 
      } 

      @Override 
      protected boolean computeValue() { 
       return textProperty().get().length() > maxLength.get(); 
      } 
     }; 
    } 
} 

अभी भी है, तथापि, "अवैध" चित्रमय प्रभाव के बारे में एक छोटी सी बात। आप यहाँ देख सकते हैं:

this.invalid.addListener(new ChangeListener<Boolean>() { 
      @Override 
      public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) { 
       if (t^t1) { 
        if (t1) { 
//      setStyle("-fx-font-weight: bold; -fx-text-fill: red;"); 
         setEffect(invalidEffect); 
        } else { 
//      setStyle("-fx-font-weight: normal; -fx-text-fill: inherit;"); 
         setEffect(null); 
        } 
       } 

      } 
     }); 

मैं setStyle लेकिन -fx-font-weight उपयोग करने के साथ करने की कोशिश की: वारिस; कोड तोड़ता है (ऐसा क्यों नहीं है क्योंकि यह इसका डिफ़ॉल्ट मान होना चाहिए)। स्टाइल क्लास इंजेक्शन करना काम नहीं करता है क्योंकि अवैध होने पर मैं इसे वापस नहीं कर सकता।

कोई सुराग? आंतरिक श्रोता को अलग करना और अन्य प्रभावों के साथ बाहर एक और संलग्न करना संभव है (f.i. TextField प्रभाव को बदलने के बजाय एक हरा टिक चिह्न दिखा रहा है)।

आप शैली वर्गों की सूची से हटाने के द्वारा यदि आप बुरा :)

उत्तर

3

तुम हमेशा एक शैली वापस कर सकते हैं कोड का उपयोग करने के लिए स्वतंत्र हैं यानी

node.getStyleClass().remove("my-style"); 
+0

मैं अब यह लेकिन यह उपयोग कर रहा हूँ बल्कि धीमा लगता है ... इसके अलावा यह छद्म-राज्य लागू नहीं करता है: अमान्य। क्या यह अमान्य चर मान पढ़ना चाहिए और छद्मस्टेट लागू नहीं करना चाहिए? – matticala

+1

मैंने ऐड/निकालें स्टाइल तकनीक का उपयोग किया है और इसे धीमा नहीं मिला है, अगर आपको कोड का यह हिस्सा वास्तव में समस्या है तो आपको मापने की आवश्यकता हो सकती है। आपको आपूर्ति की तुलना में एक राज्य रखने के लिए एक त्वचा को लागू करने की आवश्यकता है। कुछ कोड उदाहरणों के लिए https://github.com/shemnon/DeckControl/tree/master/src/main/java/com/github/shemnon/deckcontrol/skin देखें। –

+0

मैंने अनुमान लगाया। वास्तव में मैं एक उचित पुनर्वितरण नियंत्रण लागू करने के लिए कस्टम नियंत्रण (http://www.parleys.com/#st=5&id=2789&sl=35) बनाने के बारे में जावाऑन 2011 ट्यूटोरियल देख रहा हूं। मैं भी उस जिथब पर एक नज़र डालेगा, बहुत बहुत धन्यवाद! – matticala