JavaFX:Java 7.4和Java 8之间的兼容性问题

时间:2015-01-21 16:05:47

标签: checkbox javafx treeview tableview

我有一个应用程序,它大量使用JavaFX TreeView和TableView中的复选框。在JavaFX 2.2中稍后出现的增强功能之前,有很多自定义代码。

我现在发现以前工作的复选框不起作用(就像它们被禁用一样),尽管有些工作间歇性地工作。

我已经查看了Oracle兼容性文档,但我找不到任何相关内容。

我有一个小样本应用程序,它在Java 7.4中完美运行,但显示出与Java 8中的主应用程序相同的错误行为。

任何人都可以建议我从你自己的经验开始看 - 例如单元工厂,回调等 - 或者说明在Java 8中这种构造是否有任何根本改变?我在下面发布了示例应用程序代码(四个单独的类)。

提前谢谢。

package samplefx2_original_v7;  

import javafx.application.Application;  
import static javafx.application.Application.launch;  
import javafx.beans.value.ObservableValue;  
import javafx.collections.FXCollections;  
import javafx.collections.ObservableList;  
import javafx.event.EventHandler;  
import javafx.geometry.Insets;  
import javafx.scene.Group;  
import javafx.scene.Scene;  
import javafx.scene.control.Label;  
import javafx.scene.control.TableCell;  
import javafx.scene.control.TableColumn;  
import javafx.scene.control.TableColumn.CellDataFeatures;  
import javafx.scene.control.TableColumn.CellEditEvent;  
import javafx.scene.control.TableView;  
import javafx.scene.control.cell.PropertyValueFactory;  
import javafx.scene.layout.VBox;  
import javafx.scene.text.Font;  
import javafx.stage.Stage;  
import javafx.util.Callback;  

public class SampleFX2_Original_V7 extends Application {  

private TableView table = new TableView();  
private boolean everything = false;  

//Sample data for the table.  
private final ObservableList<Person> data =  
   FXCollections.observableArrayList(  
   new ControlPerson(false, "Select Columns", false, false),  
   new Person(true, "Jacob Smith", true, false),  
   new Person(true, "Isabella Johnson", true, true),  
   new Person(true, "Ethan Williams", false, false),  
   new Person(true, "Emma Jones", false, true),  
   new Person(false, "Michael Brown", true, true));  

/** 
 * @param args the command line arguments 
 */  
public static void main(String[] args) {  
 launch(args);  
}  

@Override  
public void start(Stage stage) {  
 Scene scene = new Scene(new Group());  
 stage.setTitle("Table View Sample");  
 stage.setWidth(850);  
 stage.setHeight(500);  

 final Label label = new Label("Address Book");  
 label.setFont(new Font("Arial", 20));  

 //A custom cell factory that creates checkboxes for a boolean property.  

 Callback<TableColumn, TableCell> colCheckFactory = new Callback<TableColumn, TableCell>() {  

   @Override  
   public TableCell call(TableColumn p) {  
return new CheckBoxCell();  
   }  
 };  

 //The various columns  
 TableColumn nameCol = new TableColumn("Name");  
 nameCol.setMinWidth(100);  
 nameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));  

 TableColumn contactCol = createContactColumn(colCheckFactory);  
 TableColumn emailCol = createEmailColumn(colCheckFactory);  
 TableColumn phoneCol = createPhoneColumn(colCheckFactory);  

 //Add the columns and data to the table.  
 table.setItems(data);  
 table.getColumns().addAll(nameCol, contactCol, emailCol, phoneCol);  

 //Make the table editable  
 table.setEditable(true);  
   table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);  

 final VBox vbox = new VBox();  
 vbox.setSpacing(5);  
 vbox.getChildren().addAll(label, table);  
 vbox.setPadding(new Insets(10, 0, 0, 10));  

 ((Group) scene.getRoot()).getChildren().addAll(vbox);  

 stage.setScene(scene);  
 stage.show();  
}  

private TableColumn createEmailColumn(Callback<TableColumn, TableCell> cellFactory) {  
 TableColumn emailCol = new TableColumn("Email");  
 emailCol.setMinWidth(75);  
 emailCol.setCellValueFactory(new PropertyValueFactory("email"));  
 emailCol.setCellFactory(cellFactory);  
 emailCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, Boolean>>() {  

   @Override  
   public void handle(CellEditEvent<Person, Boolean> event) {  
if (event.getRowValue() instanceof ControlPerson) {  
  for (Person p : data) {  
    p.setEmail(event.getNewValue());  
  }  
} else {  
  //Need to handle the indivdual cells as well as the special control cells.  
  Person p = event.getRowValue();  
  p.setEmail( event.getNewValue() );  
}  
   }  
 });  

 return emailCol;  
}  

private TableColumn createPhoneColumn(Callback<TableColumn, TableCell> cellFactory) {  
 TableColumn phoneCol = new TableColumn("Phone");  
 phoneCol.setMinWidth(75);  
 phoneCol.setCellValueFactory( new PropertyValueFactory("phone"));  
 phoneCol.setCellFactory(cellFactory);  
 phoneCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, Boolean>>() {  

   @Override  
   public void handle(CellEditEvent<Person, Boolean> event) {  
if (event.getRowValue() instanceof ControlPerson) {  
  for (Person p : data) {  
    p.setPhone(event.getNewValue());  
  }  
} else {  
  Person p = event.getRowValue();  
  p.setPhone( event.getNewValue() );  
}  
   }  
 });  

 return phoneCol;  
}  

/** 
 * This is the main control column in your application (containing the green and red circles). 
 * 
 * @param cellFactory 
 * @return 
 */  
private TableColumn createContactColumn( Callback<TableColumn, TableCell> cellFactory ) {  
 TableColumn contactCol = new TableColumn("Contact");  
 contactCol.setMinWidth(75);  
 contactCol.setCellValueFactory( new PropertyValueFactory( "contact"));  
 contactCol.setCellFactory(cellFactory);  
 contactCol.setOnEditCommit(new EventHandler<CellEditEvent<Person, Boolean>>() {  

   @Override  
   public void handle(CellEditEvent<Person, Boolean> event) {  
//This handler is different to the other two as it controls the checking/unchecking of both  
//the whole table and individual rows.  
if (event.getRowValue() instanceof ControlPerson) {  
  for (Person p : data) {  
    p.setContact(event.getNewValue());  
    p.setEmail(event.getNewValue());  
    p.setPhone(event.getNewValue());  
  }  

  //This is just an example of how you would control a special "everything" flag.  
  //You could call any method or take any action here to deal with the special  
  //case where everything is selected.  
  everything = event.getNewValue();  
} else {  
  //Set the state of any boolean properties to modify the whole row.  
  Person p = event.getRowValue();  
  p.setContact( event.getNewValue() );  
  p.setEmail(event.getNewValue());  
  p.setPhone(event.getNewValue());  
}  
   }  
 });  

 return contactCol;  
}  
}  


package samplefx2_original_v7;  
import javafx.beans.property.SimpleBooleanProperty;  
import javafx.beans.property.SimpleStringProperty;  
public class Person {  

private final SimpleBooleanProperty contact;  
private final SimpleStringProperty name;  
private final SimpleBooleanProperty email;  
private final SimpleBooleanProperty phone;  

public Person(boolean contact, String name, boolean email, boolean phone) {  
 this.contact = new SimpleBooleanProperty( contact );  
 this.name = new SimpleStringProperty(name);  
 this.email = new SimpleBooleanProperty( email );  
 this.phone = new SimpleBooleanProperty( phone );  
}  

public String getName() {  
 return name.get();  
}  

public void setName(String name) {  
 this.name.set(name);  
}  

public SimpleStringProperty nameProperty() {  
 return name;  
}  

public boolean isContact() {  
 return contact.get();  
}  

public void setContact( boolean contact ) {  
 this.contact.set( contact );  
}  

public SimpleBooleanProperty contactProperty() {  
 return contact;  
}  

public boolean isEmail() {  
 return email.get();  
}  

public void setEmail( boolean email ) {  
 this.email.set( email );  
}  

public SimpleBooleanProperty emailProperty() {  
 return email;  
}  

public boolean isPhone() {  
 return contact.get();  
}  

public void setPhone( boolean phone ) {  
 this.phone.set( phone );  
}  

public SimpleBooleanProperty phoneProperty() {  
 return phone;  
}  
}  


package samplefx2_original_v7;  

/** 
 * This subclass of Person is used only to identify the row(s) that is used to control 
 * the checking and unchecking of columns. 
 */  
public class ControlPerson extends Person {  

public ControlPerson(boolean active, String name, boolean email, boolean phone) {  
 super(active, name, email, phone);  
}  
}  


package samplefx2_original_v7;  

import javafx.event.ActionEvent;  
import javafx.event.EventHandler;  
import javafx.geometry.Pos;  
import javafx.scene.control.CheckBox;  
import javafx.scene.control.ContentDisplay;  
import javafx.scene.control.TableCell;  


public class CheckBoxCell extends TableCell<Person, Boolean> {  

private CheckBox checkBox;  

public CheckBoxCell() {  
 if (checkBox == null) {  
   checkBox = new CheckBox();  
   checkBox.setOnAction(new EventHandler<ActionEvent>() {  

@Override  
public void handle(ActionEvent event) {  
  CheckBox cb = (CheckBox) event.getSource();  
  getTableView().edit(getTableRow().getIndex(), getTableColumn());  
  commitEdit(cb.isSelected());  
}  
   });  
 }  
 setGraphic(checkBox);  
 setContentDisplay(ContentDisplay.GRAPHIC_ONLY);  
 //Center align the checkboxes.  
 setAlignment(Pos.CENTER);  
}  

@Override  
public void updateItem(Boolean item, boolean empty) {  
 super.updateItem(item, empty);  
 if (item == null) {  
   //If we don't have an item don't draw the checkbox.  
   setGraphic( null );  
// checkBox.setDisable(true);  
// checkBox.setSelected(false);  
 } else {  
   checkBox.setDisable(false);  
   checkBox.setSelected(item);  
 }  
}  
} 

1 个答案:

答案 0 :(得分:1)

这里发生了一些事情。一个简单的注意事项是,当单元格从空变为非空时,不设置图形。你需要:

@Override  
public void updateItem(Boolean item, boolean empty) {  
 super.updateItem(item, empty);  
 if (item == null) {  
   //If we don't have an item don't draw the checkbox.  
   setGraphic( null );  
// checkBox.setDisable(true);  
// checkBox.setSelected(false);  
 } else {  
   checkBox.setDisable(false);  
   checkBox.setSelected(item);  
   setGraphic(checkBox);
 }  
}  

但可能更多的问题是你的表格单元格实现真的依赖于未记录的行为,因为它强制表格进入编辑模式(getTableView().edit(...))并且(据我所知)似乎依赖于这样做的一些副作用是为了获得您想要的功能。因为行为没有记录,所以不能保证它在新版本中保持不变,所以我在Java 8下打破它并不会太惊讶。

实现单元格的更好方法是使用侦听器(或绑定)在复选框的selectedPropertyPerson类中的属性之间交换数据。因为无论是否正在编辑单元格,显示总是相同的(即复选框),因此不需要使用单元类中的编辑API。这是JavaFX 2.2中引入的标准CheckBoxTableCell的工作方式。

假设您想要的功能是“联系人”列复选框应选中“电子邮件”和“电话”复选框,我会略微区别。在模型类(Person)中确实没有逻辑需要具有contact属性,因为该信息已经包含在其他两个布尔属性中。 (另一种思考方式是“控制”复选框只是UI组件,而不是数据的一部分,因此它们在模型中没有位置。)您的“联系人”列实际上没有与之关联的属性它;只需将其设为TableColumn<Person, Person>并让其单元格更新其他属性。

此外,您的ControlPerson有点像黑客。同样,表中的这一行实际上只是出于用户界面的目的而不是数据的一部分。所以它真的不应该作为表items的一部分出现。我会在表头中放置“全选”复选框,而不是在表的数据部分。这会改变它们的外观(虽然你可以随时用CSS修复它),但好处是滚动时它们仍然可见,这可能是可取的。

这是一个完整的示例,它以这种方式工作,并在Java 7(JavaFX 2.2)和Java 8下运行。(我在1.7.0_65,1.8.0_25和1.8.0_40下测试。)

import java.util.Arrays;

import javafx.application.Application;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

public class SampleFX2 extends Application {

    @Override
    public void start(Stage primaryStage) {

        ObservableList<Person> data = FXCollections.observableArrayList(
                   new Callback<Person, Observable[]>() {
                       @Override
                       public Observable[] call(Person person) {
                           return new Observable[] {person.emailProperty(), person.phoneProperty()};
                       }
                   }); 

        data.addAll(Arrays.asList(  
                   new Person("Jacob Smith", true, false),  
                   new Person("Isabella Johnson", true, true),  
                   new Person("Ethan Williams", false, false),  
                   new Person("Emma Jones", false, true),  
                   new Person("Michael Brown", true, true)));

        final TableView<Person> table = new TableView<>();
        table.setItems(data);


        TableColumn<Person, String> nameCol = new TableColumn<>("Name");
        nameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("name"));

        final CheckBox allContactCheckBox = new CheckBox() ;
        final CheckBox allEmailCheckBox = new CheckBox();
        final CheckBox allPhoneCheckBox = new CheckBox();

        updateHeaderCheckBoxes(table, allContactCheckBox, allEmailCheckBox, allPhoneCheckBox);


        data.addListener(new ListChangeListener<Person>() {
            @Override
            public void onChanged(Change<? extends Person> change) {
                updateHeaderCheckBoxes(table, allContactCheckBox, allEmailCheckBox, allPhoneCheckBox);
            }

        });

        allPhoneCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> obs,
                    Boolean wasSelected, Boolean isSelected) {
                for (Person person : table.getItems()) {
                    person.setPhone(isSelected);
                }
            }
        });

        allEmailCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> obs,
                    Boolean wasSelected, Boolean isSelected) {
                for (Person person : table.getItems()) {
                    person.setEmail(isSelected);
                }
            }
        });

        allContactCheckBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> obs,
                    Boolean wasSelected, Boolean isSelected) {
                for (Person person : table.getItems()) {
                    person.setPhone(isSelected);
                    person.setEmail(isSelected);
                }
            }
        });


        TableColumn<Person, Person> contactCol = new TableColumn<>();
        contactCol.setPrefWidth(75);
        contactCol.setGraphic(createTableHeader("Contact", allContactCheckBox));
        contactCol.setCellValueFactory(new Callback<CellDataFeatures<Person, Person>, ObservableValue<Person>>() {

            @Override
            public ObservableValue<Person> call(
                    CellDataFeatures<Person, Person> person) {
                return new ReadOnlyObjectWrapper<>(person.getValue());
            }

        });

        contactCol.setCellFactory(new Callback<TableColumn<Person, Person>, TableCell<Person, Person>>() {

            @Override
            public TableCell<Person, Person> call(
                    TableColumn<Person, Person> param) {
                return new ContactCell();
            }

        });

        TableColumn<Person, Boolean> emailCol = new TableColumn<>();
        emailCol.setPrefWidth(75);
        emailCol.setGraphic(createTableHeader("Email", allEmailCheckBox));
        emailCol.setCellValueFactory(new PropertyValueFactory<Person, Boolean>("email"));
        emailCol.setCellFactory(new Callback<TableColumn<Person, Boolean>, TableCell<Person, Boolean>>() {

            @Override
            public TableCell<Person, Boolean> call(
                    TableColumn<Person, Boolean> column) {
                return new CheckBoxCell<Person>(new Callback<Person, BooleanProperty>() {

                    @Override
                    public BooleanProperty call(Person person) {
                        return person.emailProperty();
                    }

                });
            }

        });

        TableColumn<Person, Boolean> phoneCol = new TableColumn<>();
        phoneCol.setPrefWidth(75);
        phoneCol.setGraphic(createTableHeader("Phone", allPhoneCheckBox));      
        phoneCol.setCellValueFactory(new PropertyValueFactory<Person, Boolean>("phone"));
        phoneCol.setCellFactory(new Callback<TableColumn<Person, Boolean>, TableCell<Person, Boolean>>() {

            @Override
            public TableCell<Person, Boolean> call(
                    TableColumn<Person, Boolean> column) {
                return new CheckBoxCell<Person>(new Callback<Person, BooleanProperty>() {

                    @Override
                    public BooleanProperty call(Person person) {
                        return person.phoneProperty();
                    }

                });
            }

        });


        table.getColumns().add(nameCol);
        table.getColumns().add(contactCol);
        table.getColumns().add(emailCol);
        table.getColumns().add(phoneCol);

        Button showButton = new Button("Debug");
        showButton.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent evt) {
                for (Person p : table.getItems()) {
                    System.out.println(p.getName() + " " + p.isEmail() +" "+ p.isPhone());
                }
                System.out.println();
            }

        });


        HBox controls = new HBox(5);
        controls.setAlignment(Pos.CENTER);
        controls.setPadding(new Insets(10));
        controls.getChildren().add(showButton);

        BorderPane root = new BorderPane();
        root.setCenter(table);
        root.setBottom(controls);

        Scene scene = new Scene(root, 800, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Node createTableHeader(String text, CheckBox checkBox) {
        VBox header = new VBox(2);
        header.setPadding(new Insets(2));
        header.getChildren().addAll(new Label(text), checkBox);
        header.setAlignment(Pos.CENTER);
        return header ;
    }

    private static void updateHeaderCheckBoxes(final TableView<Person> table,
            final CheckBox allContactCheckBox, final CheckBox allEmailCheckBox,
            final CheckBox allPhoneCheckBox) {
        boolean allPhoneSelected = true ;
        boolean noPhoneSelected = true ;
        boolean allEmailSelected = true ;
        boolean noEmailSelected = true ;
        for (Person person : table.getItems()) {
            if (person.isEmail()) {
                noEmailSelected = false ;
            } else {
                allEmailSelected = false ;
            }
            if (person.isPhone()) {
                noPhoneSelected = false ;
            } else {
                allPhoneSelected = false ;
            }
        }
        setCheckBoxState(allPhoneSelected, noPhoneSelected, allPhoneCheckBox);
        setCheckBoxState(allEmailSelected, noEmailSelected, allEmailCheckBox);
        setCheckBoxState(allPhoneSelected && allEmailSelected, noPhoneSelected && noEmailSelected, allContactCheckBox);
    }

    private static void setCheckBoxState(boolean on, boolean off, CheckBox checkBox) {
        if (on) {
            checkBox.setIndeterminate(false);
            checkBox.setSelected(true);
        } else if (off) {
            checkBox.setIndeterminate(false);
            checkBox.setSelected(false);
        } else {
            checkBox.setIndeterminate(true);
        }
    }

    public static class ContactCell extends TableCell<Person, Person> {

        private final CheckBox checkBox ;

        public ContactCell() {
            checkBox = new CheckBox();

            final ChangeListener<Boolean> propertyListener = new ChangeListener<Boolean>() {

                @Override
                public void changed(ObservableValue<? extends Boolean> obs,
                        Boolean oldValue, Boolean newValue) {
                    updateCheckBox();
                }

            };

            checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {

                @Override
                public void changed(ObservableValue<? extends Boolean> obs,
                        Boolean oldValue, Boolean newValue) {
                    Person person = getItem();
                    person.setEmail(newValue);
                    person.setPhone(newValue);
                }

            });

            itemProperty().addListener(new ChangeListener<Person>() {

                @Override
                public void changed(
                        ObservableValue<? extends Person> observable,
                        Person oldValue, Person newValue) {
                    if (oldValue != null) {
                        oldValue.emailProperty().removeListener(propertyListener);
                        oldValue.phoneProperty().removeListener(propertyListener);
                    }
                    if (newValue != null) {
                        newValue.emailProperty().addListener(propertyListener);
                        newValue.phoneProperty().addListener(propertyListener);
                        updateCheckBox();
                    }
                }

            });

            emptyProperty().addListener(new ChangeListener<Boolean>() {

                @Override
                public void changed(ObservableValue<? extends Boolean> obs,
                        Boolean wasEmpty, Boolean isEmpty) {
                    if (isEmpty) {
                        setGraphic(null);
                    } else {
                        setGraphic(checkBox);
                    }
                }

            });

            setAlignment(Pos.CENTER);
        }

        private void updateCheckBox() {
            Person person = getItem();
            if (person != null) {
                setCheckBoxState(person.isEmail() && person.isPhone(), ! person.isEmail() && ! person.isPhone(), checkBox);
                if (person.isEmail() && person.isPhone()) {
                    checkBox.setSelected(true);
                } else if (! person.isEmail() && ! person.isPhone()) {
                    checkBox.setSelected(false);
                } else {
                    checkBox.setIndeterminate(true);
                }
                checkBox.setIndeterminate(person.isEmail() != person.isPhone());
            }
        }

    }

    public static class CheckBoxCell<T> extends TableCell<T, Boolean> {
        private final CheckBox checkBox ;

        public CheckBoxCell(final Callback<T, BooleanProperty> propertyMapper) {
            checkBox = new CheckBox();

            checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {

                @Override
                public void changed(
                        ObservableValue<? extends Boolean> observable,
                        Boolean oldValue, Boolean newValue) {
                    @SuppressWarnings("unchecked") // for some reason getTableRow() returns a raw type...
                    TableRow<T> row = getTableRow();
                    if (row != null) {
                        T item = row.getItem();
                        if (item != null) {
                            BooleanProperty property = propertyMapper.call(item);
                            property.set(newValue);
                        }
                    }
                }

            });

            itemProperty().addListener(new ChangeListener<Boolean>() {

                @Override
                public void changed(
                        ObservableValue<? extends Boolean> observable,
                        Boolean oldValue, Boolean newValue) {
                    if (newValue != null) {
                    checkBox.setSelected(newValue);
                    }
                }

            });

            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            setAlignment(Pos.CENTER);

            emptyProperty().addListener(new ChangeListener<Boolean>() {

                @Override
                public void changed(
                        ObservableValue<? extends Boolean> observable,
                        Boolean oldValue, Boolean newValue) {
                    if (newValue) {
                        setGraphic(null);
                    } else {
                        setGraphic(checkBox);
                    }
                }

            });
        }

    }

    public static class Person {  

        private final StringProperty name;  
        private final BooleanProperty email;  
        private final BooleanProperty phone;  

        public Person(String name, boolean email, boolean phone) {  
         this.name = new SimpleStringProperty(name);  
         this.email = new SimpleBooleanProperty( email );  
         this.phone = new SimpleBooleanProperty( phone );  
        }  

        public String getName() {  
         return name.get();  
        }  

        public void setName(String name) {  
         this.name.set(name);  
        }  

        public StringProperty nameProperty() {  
         return name;  
        }  

        public boolean isEmail() {  
         return email.get();  
        }  

        public void setEmail( boolean email ) {  
         this.email.set( email );  
        }  

        public BooleanProperty emailProperty() {  
         return email;  
        }  

        public boolean isPhone() {  
         return phone.get();  
        }  

        public void setPhone( boolean phone ) {  
         this.phone.set( phone );  
        }  

        public BooleanProperty phoneProperty() {  
         return phone;  
        }  
    }  

    public static void main(String[] args) {
        launch(args);
    }
}