2017-04-21 25 views
0

현재 16 진수로 인코딩 된 내용을 쉽게 입력 할 수있는 JavaFX의 사용자 지정 TextArea를 만들려고합니다. 주요 제약 조건은 다음과 같습니다JavaFX : 16 진수로 인코딩 된 내용의 사용자 지정 TextArea

  1. 텍스트는 "ff"{0xff}로 저장됩니다 예를 들어 문자열의 이진 상응를 포함하는 Property<byte[]> (에 연결되어
  2. 유일한 유효한 문자 16 진수 숫자 (abcdef)에만 있습니다.. 프레젠테이션 이유는, 상부 케이스 숫자 (예 1Bd51bd5로 표시)를 소문자로 설정된다.
  3. 지역은 두 개의 문자 블록의 16 진수 문자열을 표시한다.

세 번째 요구 사항은 대부분의 문제를 발견 한 것입니다. 지금까지 내가 수행 한 작업은 textPropertychangeListener을 추가하여 필드의 텍스트가 변경 될 때마다 형식이 유지되도록하는 것입니다. 코드는 다음과 같습니다 validated(String) 구성 요소의 형식 요구 사항을 다하는 String을 반환

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

. 이것은 새로운 문자가 삽입 될 때 매력처럼 작동합니다 : 규칙이 시행되고 사용자가 공백을 수동으로 입력 할 필요없이 형식이 보존됩니다. 내용이 삭제되고 내가 자동으로 공간을 삭제하려고하면 그러나, 더러운 예외가 생성됩니다

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을 사용하는 것이 좋습니다. 그러나 이것은 매우 엉뚱한 것입니다 (캐럿이 위치를 일반적으로 필드의 시작 부분으로 변경하고 포커스가 손실되는 경우가 있음).

제 질문은 :이 16 진수 필드에 대해 가장 좋은 방법은 무엇입니까? 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));