Javafx 2 动态JavaFX绑定

Javafx 2 动态JavaFX绑定,javafx-2,Javafx 2,我的应用程序必须处理动态绑定。 我有一个JavaBean对象列表,其中有许多必须编辑的属性。 存在具有不同属性的多种类型的对象 我创建一个树状视图来列出对象。 每次在TreeView中选择一个对象时,我都会更新屏幕中的第二个容器,在其中动态创建绑定到当前对象属性的标签和文本字段 我使用JavaBeanStringProperty、JavaBeanIntegerProperty和这个家族的其他对象来创建一个与javabean交互的属性。那很好用。 我将这些JavaBeanProperty对象中的每

我的应用程序必须处理动态绑定。 我有一个JavaBean对象列表,其中有许多必须编辑的属性。 存在具有不同属性的多种类型的对象

我创建一个树状视图来列出对象。 每次在TreeView中选择一个对象时,我都会更新屏幕中的第二个容器,在其中动态创建绑定到当前对象属性的标签和文本字段

我使用JavaBeanStringProperty、JavaBeanIntegerProperty和这个家族的其他对象来创建一个与javabean交互的属性。那很好用。 我将这些JavaBeanProperty对象中的每一个链接到它们对应的TextField的TextAttribute,以便在UI更改时更新Bean,反之亦然

问题是:每次我在TreeView中选择一个新的JavaBean时,以前动态创建的所有对象似乎都仍然是活动的。我第一次选择Bean并编辑它时,它会起作用,但第二次,它就不起作用了

我尝试创建已创建绑定的列表,以便在选择新Bean时可以解除绑定,但这是不可能的,因为StringProperties和IntegerProperty不共享公共接口,所以我可以解除绑定

有人知道如何应对吗

例如:

豆类及其特性:

  • Bean1:名称(字符串)、金额(整数)
  • Bean2:名称(字符串)、类型(字符串)
  • Bean3:名称(字符串)、地址(字符串)
如果选择Bean1,则清除容器,并将这些新对象添加到该容器中:

  • 一个表示名称的TextField,一个与Bean接口的JavaBeanStringProperty,并将其与文本字段的TextProperty双向绑定
  • 一个表示数量的TextField,一个与Bean接口的JavaBeanIntegerProperty,并使用NumberConverter将其与文本字段的TextProperty双向绑定
当我选择Bean2时,我清除容器,并将这些新对象添加到该容器中:

  • 一个表示名称的TextField,一个与Bean接口的JavaBeanStringProperty,并将其与文本字段的TextProperty双向绑定
  • 一个表示类型的TextField,一个与Bean接口的JavaBeanStringProperty,并将其与文本字段的TextProperty双向绑定
当我选择Bean3时,我清除容器,并将这些新对象添加到其中:

  • 一个表示名称的TextField,一个与Bean接口的JavaBeanStringProperty,并将其与文本字段的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);
    }

}
import java.beans.PropertyChangeEvent;
导入java.beans.PropertyChangeListener;
导入java.beans.PropertyChangeSupport;
导入java.lang.ref.WeakReference;
导入javafx.application.application;
导入javafx.beans.binding.Bindings;
导入javafx.beans.property.adapter.JavaBeanIntegerProperty;
导入javafx.beans.property.adapter.JavaBeanIntegerPropertyBuilder;
导入javafx.beans.property.adapter.JavaBeanStringProperty;
导入javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.geometry.Insets;
导入javafx.scene.scene;
导入javafx.scene.control.Label;
导入javafx.scene.control.SelectionMode;
导入javafx.scene.control.TextField;
导入javafx.scene.control.TreeItem;
导入javafx.scene.control.TreeView;
导入javafx.scene.layout.HBox;
导入javafx.scene.layout.Pane;
导入javafx.scene.layout.VBox;
导入javafx.scene.paint.Color;
导入javafx.stage.stage;
导入javafx.util.converter.NumberStringConverter;
公共类主扩展应用程序{
//=============================================================================================
公共抽象类Bean{
公共抽象void createUI(窗格容器);
}
//=============================================================================================
公共类Bean1扩展了Bean{
私有字符串名称;
私人整数金额;
私有PropertyChangeSupport pcs=新PropertyChangeSupport(此);
公共Bean1(字符串名称,整数金额){
this.name=名称;
这个。金额=金额;
}
公共字符串toString(){return name;}
public void addPropertyChangeListener(PropertyChangeListener侦听器){
pcs.addPropertyChangeListener(listener);
System.out.println(“Bean 1 PCS有“+PCS.getPropertyChangeListeners().length+”监听器。1可能已添加。”);
}   
public void removePropertyChangeListener(PropertyChangeListener侦听器){
pcs.removePropertyChangeListener(监听器);
System.out.println(“Bean 1 PCS有“+PCS.getPropertyChangeListeners().length+”监听器。1可能已被删除。”);
}   
公共字符串getName(){return name;}
公共void集合名(字符串名){
字符串last=this.name;
this.name=名称;
pcs.firePropertyChange(“名称”,最后一个,this.name);
System.out.println(“Bean 1:名称更改:“+last+”->“+this.name”);
}
public int getAmount(){return amount;}
公共无效设置金额(整数金额){
int last=此数值;
这个。金额=金额;
pcs.firePropertyChange(“金额”,最后一个,本金额);
System.out.println(“Bean 1:金额更改:“+last+”->“+this.amount”);
}
公共void createUI(窗格容器){
HBox nameContainer=新的HBox();
标签名称标签=新标签(“名称:”);
nameLabel.setPrefWidth(80);
beanPathAdaptor.setBean(myNewBean);