2017-04-21 20 views
0

我正在嘗試在JavaFX中創建一個自定義TextArea,以便於輸入十六進制編碼的內容。主要制約因素是:JavaFX:用於十六進制編碼內容的自定義TextArea

  1. 的文本鏈接到包含字符串的二進制相當於一個Property<byte[]>(如"ff"存儲爲{0xff}
  2. 唯一有效的字符是十六進制數字(abcdef)僅限。介紹的原因,上殼體位數被接通爲小寫(例如1Bd5顯示爲1bd5)。
  3. 的區域顯示的兩個字符塊的十六進制字符串。

第三個要求是我發現了大部分問題。到目前爲止,我所做的是將changeListener添加到區域的textProperty,以便每次更改字段上的文本時,格式都會保留。代碼如下所示:

textProperty().addListener(new ChangeListener<String>() { 
    @Override 
    public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) { 
     String correctedNewValue = validated(newValue); 
     if (!correctedNewValue .equals(newValue)) 
      textProperty().setValue(correctedNewValue); 
    } 
}); 

validated(String)返回String是滿足組件的格式要求。插入一個新字符時,它的作用就像一個魅力:強制執行規則並保存格式,而用戶不必手動鍵入空格。然而,當內容被刪除,我嘗試自動刪除空格,一個討厭的產生異常:

Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException 
    at javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:136) 
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:1204) 
    at javafx.scene.control.TextInputControl.updateContent(TextInputControl.java:556) 
    at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:548) 
    at javafx.scene.control.TextInputControl.deleteText(TextInputControl.java:496) 
    at javafx.scene.control.TextInputControl.deletePreviousChar(TextInputControl.java:899) 
    at com.sun.javafx.scene.control.skin.TextAreaSkin.deleteChar(TextAreaSkin.java:1351) 
    at com.sun.javafx.scene.control.behavior.TextAreaBehavior.deleteChar(TextAreaBehavior.java:274) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.deletePreviousChar(TextInputControlBehavior.java:311) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callAction(TextInputControlBehavior.java:143) 
    at com.sun.javafx.scene.control.behavior.TextAreaBehavior.callAction(TextAreaBehavior.java:259) 
    at com.sun.javafx.scene.control.behavior.BehaviorBase.callActionForEvent(BehaviorBase.java:218) 
    at com.sun.javafx.scene.control.behavior.TextInputControlBehavior.callActionForEvent(TextInputControlBehavior.java:127) 
    at com.sun.javafx.scene.control.behavior.BehaviorBase.lambda$new$74(BehaviorBase.java:135) 
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) 
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) 
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) 
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) 
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) 
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) 
    at javafx.event.Event.fireEvent(Event.java:198) 
    at javafx.scene.Scene$KeyHandler.process(Scene.java:3964) 
    at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3910) 
    at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040) 
    at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$353(GlassViewEventHandler.java:248) 
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) 
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247) 
    at com.sun.glass.ui.View.handleKeyEvent(View.java:546) 
    at com.sun.glass.ui.View.notifyKey(View.java:966) 
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) 
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) 
    at java.lang.Thread.run(Thread.java:745) 

我所看到的,到目前爲止是屬性不應該是在檢測到更改的偵聽器內被改變相同的財產,和一些來源建議使用Platform.runLater。然而,這是非常不穩定的(插入符改變了位置 - 通常是在字段的開頭 - 有時焦點會丟失)。

我的問題是:這個十六進制字段的最佳途徑是什麼?我如何正確更新textProperty? (我也願意使用現有的組件,但由於我沒有找到它,我想我可以嘗試自己構建它)。

+0

我無法讀取所有內容,但是您是否嘗試在條件中使用equalsIgnoreCase()方法? –

回答

2

您可以使用TextFormatter刪除拖尾的空格。基本上,你檢查這個改變是否是一個刪除,並且如果生成的文本以一個空格結尾,你也調整刪除的開始以刪除這個空格。

  UnaryOperator<TextFormatter.Change> filter = new UnaryOperator<TextFormatter.Change>() { 

      @Override 
      public TextFormatter.Change apply(TextFormatter.Change c) { 

       if (c.isDeleted()) { 
        if (c.getControlNewText() 
         .endsWith(" ")) { 
         c.setRange(c.getRangeStart() - 1, c.getRangeEnd()); 
        } 
       } 
       if (c.isAdded()) { 
       } 
       if (c.isReplaced()) { 
       } 
       return c; 
      } 
     }; 

     yourTextField.setTextFormatter(new TextFormatter<>(filter));