2014-04-07 3 views
3

내 응용 프로그램은 동적 바인딩을 처리해야합니다. 편집해야하는 많은 특성을 가진 Java Bean 객체 목록이 있습니다. 속성이 다른 여러 유형의 개체가 있습니다.동적 JavaFX 바인딩

개체를 나열하는 TreeView를 만듭니다. TreeView에서 하나의 개체를 선택할 때마다 현재 개체의 속성에 바인딩 된 레이블 및 TextField를 동적으로 만드는 화면에서 두 번째 컨테이너를 업데이트합니다.

JavaBeanStringProperty, JavaBeanIntegerProperty 및이 패밀리의 다른 객체를 사용하여 Java Bean과 상호 작용하는 속성을 만듭니다. 그건 완벽하게 작동합니다. 각 JavaBeanProperty 객체를 해당 TextField의 TextAttribute에 연결하므로 UI가 변경 될 때 Bean을 업데이트 할 수 있으며 그 반대의 경우도 마찬가지입니다.

문제는 : 내가 TreeView에서 새로운 Java Bean을 선택할 때마다, 이전에 동적으로 생성 된 모든 객체가 여전히 살아있는 것처럼 보입니다. 처음으로 Bean을 선택하고 편집하지만 두 번째로 더 이상 작동하지 않습니다.

생성 된 바인딩 목록을 만들려고 했으므로 새 Bean을 선택할 때 바인딩을 해제 할 수 있지만 불가능합니다. StringProperties와 IntegerProperties는 공용 인터페이스를 공유하지 않기 때문에 바인딩을 해제 할 수 있습니다.

아무도 그 문제를 해결하는 방법에 대한 아이디어가 있습니까?

예 :

콩과 그 성질 :

  • bean1을 이름 (문자열) 량 (정수)
  • Bean2 이름 (문자열) 타입 (문자열)
  • Bean3 : 이름 (문자열), 주소 (문자열)

Bean1을 선택하면 컨테이너를 지우고 새 개체를 t 모자 :

  • 이름을 나타내는 TextField, Bean과 인터페이스 할 JavaBeanStringProperty 및 텍스트 필드의 TextProperty와 함께 bidirectioninally 바인딩.
  • 금액을 나타내는 TextField, Bean과 인터페이스 할 JavaBeanIntegerProperty 및 NumberConverter를 사용하여 텍스트 필드의 TextProperty와 양방향으로 바인딩합니다. 나는 Bean2을 선택하면

, 나는 용기를 취소하고 추가하는 새로운 객체를 그에게 :

  • 가 포함 된 TextField는 이름, 콩과 인터페이스 할 수있는 JavaBeanStringProperty을 표현하고, bidirectinally 바인딩 텍스트 필드의 TextProperty.
  • 형식을 나타내는 TextField, Bean과 인터페이스 할 JavaBeanStringProperty 및 텍스트 필드의 TextProperty와 양방향으로 바인딩합니다.나는 Bean3을 선택하면

, 나는 용기를 취소하고 추가하는 새로운 객체를 그에게 :

  • 가 포함 된 TextField는 이름, 콩과 인터페이스 할 수있는 JavaBeanStringProperty을 표현하고, bidirectinally 바인딩 텍스트 필드의 TextProperty.
  • 주소를 나타내는 TextField, Bean과 인터페이스 할 JavaBeanStringProperty 및 텍스트 필드의 TextProperty와 양방향으로 바인딩합니다.

    import java.beans.PropertyChangeEvent; 
    import java.beans.PropertyChangeListener; 
    import java.beans.PropertyChangeSupport; 
    import java.lang.ref.WeakReference; 
    
    import javafx.application.Application; 
    import javafx.beans.binding.Bindings; 
    import javafx.beans.property.adapter.JavaBeanIntegerProperty; 
    import javafx.beans.property.adapter.JavaBeanIntegerPropertyBuilder; 
    import javafx.beans.property.adapter.JavaBeanStringProperty; 
    import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder; 
    import javafx.beans.value.ChangeListener; 
    import javafx.beans.value.ObservableValue; 
    import javafx.geometry.Insets; 
    import javafx.scene.Scene; 
    import javafx.scene.control.Label; 
    import javafx.scene.control.SelectionMode; 
    import javafx.scene.control.TextField; 
    import javafx.scene.control.TreeItem; 
    import javafx.scene.control.TreeView; 
    import javafx.scene.layout.HBox; 
    import javafx.scene.layout.Pane; 
    import javafx.scene.layout.VBox; 
    import javafx.scene.paint.Color; 
    import javafx.stage.Stage; 
    import javafx.util.converter.NumberStringConverter; 
    
    public class Main extends Application { 
    
        //============================================================================================= 
        public abstract class Bean { 
         public abstract void createUI(Pane container); 
        } 
    
        //============================================================================================= 
        public class Bean1 extends Bean { 
         private String name; 
         private int amount; 
    
         private PropertyChangeSupport pcs = new PropertyChangeSupport(this); 
    
         public Bean1(String name, int amount) { 
          this.name = name; 
          this.amount = amount; 
         } 
    
         public String toString() { return name; } 
    
         public void addPropertyChangeListener(PropertyChangeListener listener) { 
          pcs.addPropertyChangeListener(listener); 
          System.out.println("Bean 1 PCS has " + pcs.getPropertyChangeListeners().length + " listeners. 1 was possuibly added."); 
         } 
    
         public void removePropertyChangeListener(PropertyChangeListener listener) { 
          pcs.removePropertyChangeListener(listener); 
          System.out.println("Bean 1 PCS has " + pcs.getPropertyChangeListeners().length + " listeners. 1 was possuibly removed."); 
         } 
    
         public String getName() { return name; } 
    
         public void setName(String name) { 
          String last = this.name; 
          this.name = name; 
          pcs.firePropertyChange("name", last, this.name); 
          System.out.println("Bean 1: name changed: " + last + " -> " + this.name); 
         } 
    
         public int getAmount() { return amount; } 
    
         public void setAmount(int amount) { 
          int last = this.amount; 
          this.amount = amount; 
          pcs.firePropertyChange("amount", last, this.amount); 
          System.out.println("Bean 1: amount changed: " + last + " -> " + this.amount); 
         } 
    
         public void createUI(Pane container) { 
          HBox nameContainer = new HBox(); 
          Label nameLabel = new Label("name: "); 
          nameLabel.setPrefWidth(80); 
          TextField nameValue = new TextField(); 
          nameValue.setPrefWidth(140); 
    
          try { 
           JavaBeanStringProperty wrapper = new JavaBeanStringPropertyBuilder().bean(this).name("name").build(); 
           nameValue.textProperty().bindBidirectional(wrapper); 
          } catch (NoSuchMethodException e) { 
           e.printStackTrace(); 
           System.out.println("Exception binding Bean 1 name property."); 
          } 
    
          nameContainer.getChildren().addAll(nameLabel, nameValue); 
    
          HBox amountContainer = new HBox(); 
          Label amountLabel = new Label("amount: "); 
          amountLabel.setPrefWidth(80); 
          TextField amountValue = new TextField(); 
          amountValue.setPrefWidth(140); 
    
          try { 
           JavaBeanIntegerProperty wrapper = new JavaBeanIntegerPropertyBuilder().bean(this).name("amount").build(); 
           Bindings.bindBidirectional(amountValue.textProperty(), wrapper, new NumberStringConverter()); 
          } catch (NoSuchMethodException e) { 
           e.printStackTrace(); 
           System.out.println("Exception binding Bean 1 amount property."); 
          } 
    
          amountContainer.getChildren().addAll(amountLabel, amountValue); 
    
          container.getChildren().clear(); 
          container.getChildren().addAll(nameContainer, amountContainer); 
         } 
        } 
    
        //============================================================================================= 
        public class Bean2 extends Bean { 
         private String name; 
         private String type; 
    
         private PropertyChangeSupport pcs = new PropertyChangeSupport(this); 
    
         public Bean2(String name, String type) { 
          this.name = name; 
          this.type = type; 
         } 
    
         public String toString() { return name; } 
    
         public void addPropertyChangeListener(PropertyChangeListener listener) { 
          pcs.addPropertyChangeListener(listener); 
          System.out.println("Bean 2 PCS has " + pcs.getPropertyChangeListeners().length + " listeners. 1 was possuibly added."); 
         } 
    
         public void removePropertyChangeListener(PropertyChangeListener listener) { 
          pcs.removePropertyChangeListener(listener); 
          System.out.println("Bean 2 PCS has " + pcs.getPropertyChangeListeners().length + " listeners. 1 was possuibly removed."); 
         } 
    
         public String getName() { return name; } 
    
         public void setName(String name) { 
          String last = this.name; 
          this.name = name; 
          pcs.firePropertyChange("name", last, this.name); 
          System.out.println("Bean 2: name changed: " + last + " -> " + this.name); 
         } 
    
         public String getType() { return type; } 
    
         public void setType(String type) { 
          String last = this.type; 
          this.type = type; 
          pcs.firePropertyChange("type", last, this.type); 
          System.out.println("Bean 2: type changed: " + last + " -> " + this.type); 
         } 
    
         public void createUI(Pane container) { 
          HBox nameContainer = new HBox(); 
          Label nameLabel = new Label("name: "); 
          nameLabel.setPrefWidth(80); 
          TextField nameValue = new TextField(); 
          nameValue.setPrefWidth(140); 
    
          try { 
           JavaBeanStringProperty wrapper = new JavaBeanStringPropertyBuilder().bean(this).name("name").build(); 
           nameValue.textProperty().bindBidirectional(wrapper); 
          } catch (NoSuchMethodException e) { 
           e.printStackTrace(); 
           System.out.println("Exception binding Bean 2 name property."); 
          } 
    
          nameContainer.getChildren().addAll(nameLabel, nameValue); 
    
          HBox typeContainer = new HBox(); 
          Label typeLabel = new Label("type: "); 
          typeLabel.setPrefWidth(80); 
          TextField typeValue = new TextField(); 
          typeValue.setPrefWidth(140); 
    
          try { 
           JavaBeanStringProperty wrapper = new JavaBeanStringPropertyBuilder().bean(this).name("type").build(); 
           typeValue.textProperty().bindBidirectional(wrapper); 
          } catch (NoSuchMethodException e) { 
           e.printStackTrace(); 
           System.out.println("Exception binding Bean 2 type property."); 
          } 
    
          typeContainer.getChildren().addAll(typeLabel, typeValue); 
    
          container.getChildren().clear(); 
          container.getChildren().addAll(nameContainer, typeContainer); 
         } 
        } 
    
        //============================================================================================= 
        public class Bean3 extends Bean { 
         private String name; 
         private String address; 
    
         private PropertyChangeSupport pcs = new PropertyChangeSupport(this); 
    
         public Bean3(String name, String address) { 
          this.name = name; 
          this.address = address; 
         } 
    
         public String toString() { return name; } 
    
         public void addPropertyChangeListener(PropertyChangeListener listener) { 
          pcs.addPropertyChangeListener(listener); 
          System.out.println("Bean 3 PCS has " + pcs.getPropertyChangeListeners().length + " listeners. 1 was possuibly added."); 
         } 
    
         public void removePropertyChangeListener(PropertyChangeListener listener) { 
          pcs.removePropertyChangeListener(listener); 
          System.out.println("Bean 3 PCS has " + pcs.getPropertyChangeListeners().length + " listeners. 1 was possuibly removed."); 
         } 
    
         public String getName() { return name; } 
    
         public void setName(String name) { 
          String last = this.name; 
          this.name = name; 
          pcs.firePropertyChange("name", last, this.name); 
          System.out.println("Bean 3: name changed: " + last + " -> " + this.name); 
         } 
    
         public String getAddress() { return address; } 
    
         public void setAddress(String address) { 
          String last = this.address; 
          this.address = address; 
          pcs.firePropertyChange("type", last, this.address); 
          System.out.println("Bean 3: address changed: " + last + " -> " + this.address); 
         } 
    
         public void createUI(Pane container) { 
          HBox nameContainer = new HBox(); 
          Label nameLabel = new Label("name: "); 
          nameLabel.setPrefWidth(80); 
          TextField nameValue = new TextField(); 
          nameValue.setPrefWidth(140); 
    
          try { 
           JavaBeanStringProperty wrapper = new JavaBeanStringPropertyBuilder().bean(this).name("name").build(); 
           nameValue.textProperty().bindBidirectional(wrapper); 
          } catch (NoSuchMethodException e) { 
           e.printStackTrace(); 
           System.out.println("Exception binding Bean 3 name property."); 
          } 
    
          nameContainer.getChildren().addAll(nameLabel, nameValue); 
    
          HBox addressContainer = new HBox(); 
          Label addressLabel = new Label("type: "); 
          addressLabel.setPrefWidth(80); 
          TextField addressValue = new TextField(); 
          addressValue.setPrefWidth(140); 
    
          try { 
           JavaBeanStringProperty wrapper = new JavaBeanStringPropertyBuilder().bean(this).name("address").build(); 
           addressValue.textProperty().bindBidirectional(wrapper); 
          } catch (NoSuchMethodException e) { 
           e.printStackTrace(); 
           System.out.println("Exception binding Bean 3 address property."); 
          } 
    
          addressContainer.getChildren().addAll(addressLabel, addressValue); 
    
          container.getChildren().clear(); 
          container.getChildren().addAll(nameContainer, addressContainer); 
         } 
        } 
    
        //============================================================================================= 
        private class TreeItemRefresher implements PropertyChangeListener { 
         private String property; 
         private WeakReference<TreeItem<Bean>> treeItem; 
    
         TreeItemRefresher(String property, TreeItem<Bean> treeItem) { 
          this.property = property; 
          this.treeItem = new WeakReference<>(treeItem); 
         } 
    
         @Override 
         public void propertyChange(PropertyChangeEvent evt) { 
          if (property.equals(evt.getPropertyName())) { 
           // Workaround to repaint the tree item when its value object changes. 
           TreeItem<Bean> item = treeItem.get(); 
           if (item != null) { 
            item.setExpanded(false); 
            item.setExpanded(true); 
           } 
          } 
         } 
        } 
    
        //============================================================================================= 
        private TreeView<Bean> treeView = new TreeView<>(); 
        private VBox container = new VBox(); 
    
        //============================================================================================= 
        @SuppressWarnings("unchecked") 
        @Override 
        public void start(Stage primaryStage) { 
         primaryStage.setTitle("Dynamic Bindings tests."); 
    
         HBox mainContainer = new HBox(); 
    
         container.setPadding(new Insets(10)); 
    
         // Creating beans. 
         Bean1 bean1 = new Bean1("Bean 1", 10); 
         Bean2 bean2 = new Bean2("Bean 2", "Type O"); 
         Bean3 bean3 = new Bean3("Bean 3", "10, Central Park Av."); 
    
         // Creating TreeView 
         treeView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); 
         treeView.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<TreeItem<Bean>>() { 
          @Override 
          public void changed(ObservableValue<? extends TreeItem<Bean>> arg0, TreeItem<Bean> oldValue, TreeItem<Bean> newValue) { 
           Bean newItem = newValue.getValue(); 
           newItem.createUI(container); 
          } 
         }); 
    
         TreeItem<Bean> bean1item = new TreeItem<Bean>(bean1); 
         bean1.addPropertyChangeListener(new TreeItemRefresher("name", bean1item)); 
    
         TreeItem<Bean> bean2item = new TreeItem<Bean>(bean2);    
         bean2.addPropertyChangeListener(new TreeItemRefresher("name", bean2item)); 
    
         TreeItem<Bean> bean3item = new TreeItem<Bean>(bean3); 
         bean3.addPropertyChangeListener(new TreeItemRefresher("name", bean3item)); 
    
         bean1item.setExpanded(true); 
         treeView.setRoot(bean1item); 
         bean1item.getChildren().addAll(bean2item, bean3item); 
    
         mainContainer.getChildren().addAll(treeView, container); 
    
         Scene scene = new Scene(mainContainer, 500, 300, Color.WHITE);   
         primaryStage.setScene(scene); 
         primaryStage.show(); 
        } 
    
        //============================================================================================= 
        public Main() { 
        } 
    
        //============================================================================================= 
        public static void main(String[] args) { 
         launch(Main.class, args); 
        } 
    
    } 
    

    공지 때로는 완벽하게 처리되지 않는 필드로 변경 :

은 여기에 전체 코드의 예입니다. 선택한 Bean을 변경하면 PropertyChangeListeners의 수가 항상 증가합니다. 나는 그것이 일어나는 이유를 안다. 그러나 나는 정말로 그것을 다루는 방법을 모른다.

더 좋은 방법이 있습니까? 알림 Bean 객체를 변경할 수 없습니다. 그들은 내 통제하에 있지 않습니다.

대단히 감사합니다.

답변

0

JFXtras BeanPathAdaptor를 사용해 보셨습니까? POJOS를 기반으로하는 동적 바인딩을위한 멋진 라이브러리입니다.

당신은 당신이 당신의 빈을 변경하려면

beanPathAdaptor.setBean(myNewBean); 

을 사용해야합니다! http://ugate.wordpress.com/2012/07/30/javafx-programmatic-pojo-expression-bindings-part-iii/

편집

내가 자바 FX 3 개 사용자 지정 구성 요소, 각 유형을 정의하는 것입니다 볼 수있는 다른 방법 : 여기

는 링크입니다. 그 (것)들에서 당신은 당신의 bean에 바인딩 된 뷰로 당신의 bean에 대한 완전한 바인딩을 정의하고 "setBean1 (Bean1 bean)"과 같은 입력 메소드를 추가합니다.

그런 다음이 컴포넌트를 인스턴스화하고 보여 주며 내용을 설정합니다 "setBean1 (...)"을 사용하십시오. 당신은 다른 유형들과 똑같이 할 수 있습니다. 물론 모든 바인딩은 정적이지만 구성 요소의 생성 및 사용은 동적이며 구성 요소 중심이며 높은 결합 (뷰 모델)입니다.

최적화하려면 이미 만들어진 모든 구성 요소를 메모리에 유지하고 다시 인스턴스를 지불하지 못하게하려면 다시 사용하십시오. 그렇지 않은 경우 가장 좋은 방법은 visible == false로 설정해야합니다. 그것들을 사용하면 원하는 경우 초기화시 구성 요소의 가능한 모든 경우를 열망 할 수 있습니다.

+0

나는 그것을 살펴볼 것이다. 그러나 여기서 문제는 UI 요소의 동적 생성과 관련됩니다. 더 나은 접근법이 있다고 생각합니까? – Marcus

+0

@Marcus Java bean에서 양식과 같은 구성 요소를 생성하려면 FXForm2를 참고해야합니다. http://dooapp.github.io/FXForm2/ – zenbeni