2014-10-16 4 views
1


구성 클래스의 변수에 연결된 gui 요소 (내 경우에는 javafx, TextField)에 대한 적절한 업데이트 전략을 찾고 있습니다. 이 규칙은 fullfilled해야 할 :
1) 나는 GUI 요소 (텍스트 필드)를 새로 고침하는 데 필요한 설정 클래스의 변수를 설정하면
2)이 텍스트 필드를 변경하면 설정 클래스의 변수는
를 새로 고침 할 필요가 3) 텍스트 필드 변경으로 인해 구성 클래스의 변수가 변경된 경우에만 조치를 취해야합니다.
4) 구성에서 변수를 변경하면 조치가 취해지기를 원하지 않습니다. 즉, 통지받을 리스너입니다.양방향 바인딩이있는 javafx gui 업데이트 전략

는 다음과 같이 가정합니다

Gui.java 
public TextField textField = new TextField(); 



Config.java 
public StringProperty stringProperty = new StringProperty(); 
stringProperty .addListener(new ChangeListener<String>() { 
     @Override 
     public void changed(ObservableValue<? extends String> arg0, String arg1, String arg2) { 
      System.out.println("config string changed"). 

     } 
    }); 


    public void update(){ 
    // now this is causing the problem because the listener 
    // will know about this set() obviously 
    stringProperty.set("bad idea"); 
    } 


Controller.java 
Gui gui = new Gui(); 
Config config = new Config(); 

// setup connection between gui element and config 
gui.textField.textProperty().bindBidirectional(config.stringProperty); 

내가 다시 추가 후 값을 설정하고 전에 ChangeListener를 제거 할 수 있다는 사실을 알고 있지만, 대한 적절한 솔루션이 있다면 제가 궁금하네요 이런 문제.

편집 : 실제로 내가 알아야 할 것은 : 바인딩 (또는) 때문에 set()이 호출 되었기 때문입니다. 이것이 어떻게 든 가능하다면 내 문제가 해결 될 것입니다.

감사합니다.

건배!

+0

을 (3) 조금? 텍스트 입력란 (예 : 각 키 누름 등)에서 텍스트가 변경 될 때마다 또는 사용자가 변경 사항을 "커밋"(예 : Enter 키를 눌러서) 할 때만이 작업을 수행 하시겠습니까? –

+0

나는 모든 변화를 원합니다. 이것은 양방향 바인딩과 잘 호환됩니다. 나의 유일한 관심사는 청취자를 "화나게하는"세트에 관한 것입니다. 업데이트 메서드가 다른 클래스에서 호출 될 수 있음을 명확히하기 위해 코드를 편집했습니다. – blaster

답변

0

당신은 항상 청취자의 한 쌍의 결합 양방향 모방 할 수 있습니다 값이 정말 리스너를 통지하기 전에 변경되는 경우가 있으므로,

StringProperty a = new SimpleStringProperty(""); 
StringProperty b = new SimpleStringProperty(""); 

a.addListener((obs, oldValue, newValue) -> { 
    b.set(newValue); 
}); 

b.addListener((obs, oldValue, newValue) -> { 
    a.set(newValue); 
}); 

속성 클래스의 set 방법

확인 충분히 똑똑를 여기에서 무한 재귀 문제에 빠지지 마십시오 (부동 소수점 유형을 사용하는 경우 매우주의해야합니다).

"other"속성의 상태가 리스너 코드에 대한 접근 방법을 결정하는 데 도움이되므로 도움이됩니다. 이 시나리오에서는

a.set("update"); 

를 호출 고려 우리는이 :

  1. ab 우리는 a.set("update")
  2. a"update"에 그 값을 변경 전화
  3. 모두 빈 문자열, b는 여전히 빈 문자열
  4. a이 변경되었으므로, lis tener는 oldValue=""newValue=a.get()="update"과 함께 호출됩니다. newValue
  5. a의 청취자 b.set("update")를 호출에 다른 값을 반환 b.get() 것을 유의 이제 ab 그 청취자는 oldValue=""newValue="update"를 호출, b 이후 두 "update"
  6. 이 변경됩니다. 이 경우 a.get()newValue과 동일한 값을 반환합니다.
  7. b의 청취자는 no-op (a는 이미 해당 값을 가짐) 인 a.set("update")을 호출합니다. 다음과 같이

그래서 지금 당신은 청취자를 작성할 수 있습니다

a.addListener((obs, oldValue, newValue) -> { 
    if (b.get().equals(newValue)) { 
     // change to a occurred via a change to b 
    } else { 
     // change to a occurred via a call to a.set(...) 
     b.set(newValue); 
    } 
}); 

b.addListener((obs, oldValue, newValue) -> { 
    if (a.get().equals(newValue)) { 
     // change to b occurred via a change to a 
    } else { 
     // change to b occurred via a call to b.set(...) 
     a.set(newValue); 
    } 
}); 

를 특정 예에서 당신과 같이 할 수 있습니다 : 당신이 명확히 수

gui.textField.textProperty().addListener((obs, oldText, newText) -> 
    config.stringProperty().set(newText)); 

config.stringProperty().addListener((obs, oldText, newText) -> { 
    if (gui.textField.getText().equals(newText)) { 
     System.out.println("Text field was changed to: "+newText); 
    } else { 
     gui.textField.setText(newText); 
    } 
}); 
+0

안녕 James_D, 귀하의 제안을 주셔서 감사하지만 그들은 processUserTextUpdate() 메서드를 구현하도록 강요합니다 - gui 요소가 포함 된 클래스의 메서드. 나는 GUI 구성 요소가 다른 클래스에있을 수있는 반면, 솔루션 구성 요소 속성에 내 청취자를 배치 할 수있는 솔루션을 선호합니다. 솔루션은 stringProperty.set()을 설정할 때 changelistener가 호출되어서는 안된다는 방향으로 가야한다고 생각합니다. – blaster

+0

사실 내가 알아야 할 것은 무엇입니까? 바인딩 (또는 set()) 때문에 호출 된 change()입니다. 이것이 어떻게 든 가능하다면 내 문제가 해결 될 것입니다. – blaster

+0

변경된 답변이 명확 해졌습니다. –