2013-07-15 2 views
0

현재 JAXB에서 생성 된 POJO를 사용하여 모든 Java 속성을 JavaFX 구성 요소에 바인딩합니다. 이를 위해, 나는 다음과 같이 진행 : POJO와 JavaFX 구성 요소 간의 바인딩 문제

  • 나는 POJO 바인딩을 지원 (support)하는 의해 PropertyChangeSupport을 추가 JAXB의 기본 생성을 변경했습니다.
  • 입력시 클래스 인스턴스를 가져 와서 Map을 반환합니다. 은 속성 자체이고 값은 속성의 값으로 바인딩 된 구성 요소입니다.
  • 반환 된지도는 JFXPanel에 표시됩니다.

    public static Map<Field, Node> createComponents(Object obj) throws NoSuchMethodException 
    { 
         Map<Field, Node> map = new LinkedHashMap<Field, Node>(); 
    
         for (final Field field : obj.getClass().getDeclaredFields()) 
         { 
          @SuppressWarnings("rawtypes") 
          Class fieldType = field.getType(); 
    
          if (fieldType.equals(boolean.class) || (fieldType.equals(Boolean.class))) //Boolean 
          { 
           map.put(field, createBool(obj, field)); 
          } 
          else if (fieldType.equals(int.class) || (fieldType.equals(Integer.class))) //Integer 
          { 
           map.put(field, createInt(obj, field)); 
          } 
          else if (fieldType.equals(BigInteger.class)) //BigInteger 
          { 
           map.put(field, createBigInt(obj, field)); 
          } 
          else if (fieldType.equals(long.class) || fieldType.equals(Long.class)) //Long 
          { 
           map.put(field, createLong(obj, field)); 
          } 
          else if (fieldType.equals(String.class)) //String 
          { 
           map.put(field, createString(obj, field)); 
    
          } 
          ... 
         } 
         return map; 
    } 
    
    public static Node createBool(Object obj, final Field field) throws NoSuchMethodException 
    { 
    
         System.out.println(field.getType().getSimpleName() + " spotted"); 
         JavaBeanBooleanProperty boolProperty = JavaBeanBooleanPropertyBuilder.create().bean(obj).name(field.getName()).build(); 
         boolProperty.addListener(new ChangeListener<Boolean>() { 
         @Override 
         public void changed(ObservableValue<? extends Boolean> arg0, Boolean arg1, Boolean arg2) 
         { 
          prettyPrinter(field, arg1, arg2); 
         } 
         }); 
         CheckBox cb = new CheckBox(); 
         cb.setText(" : " + field.getName()); 
         cb.selectedProperty().bindBidirectional(boolProperty); 
         return cb; 
    
    } 
    
    public static Node createInt(Object obj, final Field field) throws NoSuchMethodException 
    { 
         System.out.println(field.getType().getSimpleName() + " spotted"); 
         JavaBeanIntegerProperty intProperty = JavaBeanIntegerPropertyBuilder.create().bean(obj).name(field.getName()).build(); 
         StringProperty s = new SimpleStringProperty(); 
         StringConverter sc = new IntegerStringConverter(); 
         Bindings.bindBidirectional(s, intProperty, sc); 
         s.addListener(new ChangeListener<String>() { 
         @Override 
         public void changed(ObservableValue<? extends String> arg0, String arg1, String arg2) 
         { 
          prettyPrinter(field, arg1, arg2); 
         } 
         }); 
    
         TextField tf = new TextField(); 
         tf.textProperty().bindBidirectional(s); 
    
         return tf; 
    
    } 
    

    그래서, 내가 가지고있는 문제는 다음과 같습니다 : 나는 변경 대부분의 경우, 예를 들어,에 textField는 POJO 속성은 통지를하지 않습니다

여기 내 공장의 샘플입니다. 그러나 어떤 경우 POJO의 필드 순서를 변경하면 모든 청취자가 변경 사항을 인식하게됩니다. 여기

내가 속성 순서가 같은 바인딩에 영향을 미칠 수 있는지 궁금하네요 (현재 작동하는) GUI에서 다음 Personne 클래스와 어떻게 생겼는지의 예를

GUI Example

public class Personne 
{ 

    private int     taille; 

    private Boolean    lol; 

    private long     pointure; 

    private BigInteger   age; 

    private boolean    zombified; 

    private String    name; 

    private PropertyChangeSupport _changeSupport = new PropertyChangeSupport(this); 

    public Boolean getLol() 
    { 
     return this.lol; 
    } 

    public long getPointure() 
    { 
     return this.pointure; 
    } 

    public int getTaille() 
    { 
     return taille; 
    } 

    public boolean getZombified() 
    { 
     return zombified; 
    } 

    public BigInteger getAge() 
    { 
     return age; 
    } 

    public String getName() 
    { 
     return name; 
    } 

    public void setPointure(long pointure) 
    { 

     final long prev = this.pointure; 
     this.pointure = pointure; 
     _changeSupport.firePropertyChange("pointure", prev, pointure); 
    } 

    public void setTaille(int taille) 
    { 
     final int prev = this.taille; 
     this.taille = taille; 
     _changeSupport.firePropertyChange("taille", prev, taille); 
    } 

    public void setAge(BigInteger age) 
    { 
     final BigInteger prev = this.age; 
     this.age = age; 
     _changeSupport.firePropertyChange("age", prev, age); 

    } 

    public void setName(String name) 
    { 
     final String prev = this.name; 
     this.name = name; 
     _changeSupport.firePropertyChange("name", prev, name); 
    } 

    public void setLol(Boolean lol) 
    { 
     final Boolean prev = this.lol; 
     this.lol = lol; 
     _changeSupport.firePropertyChange("lol", prev, lol); 
    } 

    public void setZombified(boolean zombified) 
    { 
     final boolean prev = this.zombified; 
     this.zombified = zombified; 
     _changeSupport.firePropertyChange("zombified", prev, zombified); 

    } 

    public void addPropertyChangeListener(final PropertyChangeListener listener) 
    { 
     _changeSupport.addPropertyChangeListener(listener); 
    } 
} 

입니다 그. 게다가, HBox에 래핑 된 노드를 반환하고 싶다면 바인딩이 더 이상 작동하지 않는다는 것을 알았습니다.

내가 잘못 생각하고 있다고 생각하지만, 무엇을 알아 내지 못하니.

답변

1

JavaBeanIntegerProperty 및 JavaBeanBooleanProperty가 너무 일찍 가비지 수집됩니다.

Property.bind(Observable) 메서드는 관찰 가능 항목에 대한 강력한 참조를 유지하지만, 관찰 가능 속성에 대한 약한 참조 만 보유합니다! (속성에 WeakReference 만있는 Observable에 Listener를 등록합니다). 마찬가지로 Bindings.bindBidirectional(Property, Property)을 호출하면 두 속성은 서로 약한 참조를 유지합니다! 이것은 문서에서 찾기가 매우 어려운 매우 중요한 세부 사항입니다.

JavaFX 객체와 만 상호 작용하는 경우 JavaFX 객체는 자연스럽게 모든 속성에 대한 강력한 참조를 보유하기 때문에 문제가되지 않습니다. 그러나 JavaBeanIntegerProperty를 사용하여 레거시 객체에서 Bean 속성을 래핑하는 경우 Bean은 JavaBeanIntegerProperty에 대한 강력한 참조를 보유하지 않으므로 gc 후에 Property가 사라지고 Bean 업데이트가 중지됩니다! 나는 이것이 JavaBeanIntegerProperty의 디자인 버그라고 생각한다.

해결 방법은 바인딩을 Java Bean 업데이트 유지하려는 한 JavaBeanIntegerProperty를 필드에 할당하고 저장하는 것입니다.

또는 빈에서 Property에 대한 강력한 참조 (예 : bean에 대한 addPropertyChangeListener)가 영원히 들리도록하기 위해 뭔가를하는 속성 서브 클래스를 작성할 수 있습니다.

관련 문제