用于 TableView 的 JavaFX 属性 适配器
JavaFX property adapter for TableView
对于 DTO,我使用 POJO。因此,为了进行双向绑定,我创建了适配器。我的意思是,类似的东西:
POJO:
public class Temp{
private BigDecimal weight;
private final PropertyChangeSupport propertyChangeSupport;
public Temp() {
this.propertyChangeSupport = new PropertyChangeSupport(this);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public BigDecimal getWeight() {
return weight;
}
public void setWeight(BigDecimal weight) {
BigDecimal pv = this.weight;
this.weight = weight;
propertyChangeSupport.firePropertyChange("weight", pv, weight);
}
}
我有以下适配器:
public class TempAdapter {
private ObjectProperty<BigDecimal> weightProperty;
public TempAdapter(Temp temp) {
try {
weightProperty=new JavaBeanObjectPropertyBuilder<BigDecimal>().bean(temp).name("weight").build();
weightProperty.addListener(new ChangeListener<BigDecimal>() {
@Override
public void changed(ObservableValue<? extends BigDecimal> ov, BigDecimal t, BigDecimal t1) {
....
}
});
} catch (NoSuchMethodException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
}
public ObjectProperty<BigDecimal> getWeightProperty() {
return weightProperty;
}
但是,我不明白如何将此适配器与 TableView 一起使用。我想为 TableView 使用适配器的原因是,如果我们将 POJO 用于带有 TableView 的 DTO,我们将不得不在 TableView 中复制适配器的代码。
据我所知,对于 TableView 中的每一行,我们都必须创建一个新的适配器实例,但我不知道该怎么做。
没有适配器的解决方案class
首先请注意,您不一定需要适配器 class;您可以只在需要的地方创建 JavaBeanProperty
个实例:在本例中是在 table 的单元格值工厂中。如果 UI 中只有一个(或两个)位置需要直接绑定到与 POJO 中的属性相对应的 JavaFX 属性,那么这可能是要走的路。
这是此技术的完整示例,使用的是常用的 Oracle Person
table 示例。在此示例中,没有适配器 class:table 只是在单元格值工厂中创建了 JavaBeanStringProperty
适配器。有一个编辑表单,它直接与 POJO class 交互。
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javafx.application.Application;
import javafx.beans.property.adapter.JavaBeanStringProperty;
import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class PojoTable extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Person> table = new TableView<>();
table.setEditable(true);
TableColumn<Person, String> firstNameColumn = createColumn("First Name", "firstName");
TableColumn<Person, String> lastNameColumn = createColumn("Last Name", "lastName");
table.getColumns().add(firstNameColumn);
table.getColumns().add(lastNameColumn);
Button button = new Button("Show data");
button.setOnAction(e -> {
table.getItems().stream().map(person -> person.getFirstName() + " " + person.getLastName())
.forEach(System.out::println);
System.out.println();
});
Button edit = new Button("Edit");
edit.disableProperty().bind(table.getSelectionModel().selectedItemProperty().isNull());
edit.setOnAction(e -> edit(table.getSelectionModel().getSelectedItem(), primaryStage));
table.getItems().addAll(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
HBox buttons = new HBox(10, button, edit);
buttons.setAlignment(Pos.CENTER);
BorderPane root = new BorderPane(table, null, null, buttons, null);
BorderPane.setAlignment(buttons, Pos.CENTER);
BorderPane.setMargin(buttons, new Insets(10));
root.setPadding(new Insets(10));
primaryStage.setScene(new Scene(root, 600, 600));
primaryStage.show();
}
private void edit(Person person, Stage primaryStage) {
GridPane editPane = new GridPane();
TextField firstNameField = new TextField(person.getFirstName());
TextField lastNameField = new TextField(person.getLastName());
Button okButton = new Button("OK");
Button cancelButton = new Button("Cancel");
HBox buttons = new HBox(10, okButton, cancelButton);
editPane.addRow(0, new Label("First Name:"), firstNameField);
editPane.addRow(1, new Label("Last Name:"), lastNameField);
editPane.add(buttons, 0, 2, 2, 1);
GridPane.setHalignment(buttons, HPos.CENTER);
GridPane.setMargin(buttons, new Insets(10));
editPane.setPadding(new Insets(10));
Scene scene = new Scene(editPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.initOwner(primaryStage);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
cancelButton.setOnAction(e -> stage.hide());
okButton.setOnAction(e -> {
person.setFirstName(firstNameField.getText());
person.setLastName(lastNameField.getText());
stage.hide();
});
stage.show();
}
private TableColumn<Person, String> createColumn(String title, String property) {
TableColumn<Person, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> {
Person p = cellData.getValue();
try {
JavaBeanStringProperty prop = new JavaBeanStringPropertyBuilder()
.bean(p)
.name(property)
.build();
return prop;
} catch (Exception e) {
throw new RuntimeException(e);
}
});
col.setCellFactory(TextFieldTableCell.forTableColumn());
return col ;
}
public static class Person {
private String firstName ;
private String lastName ;
private PropertyChangeSupport support ;
public Person(String firstName, String lastName) {
this.firstName = firstName ;
this.lastName = lastName ;
support = new PropertyChangeSupport(this);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
String previous = this.firstName ;
this.firstName = firstName;
support.firePropertyChange("firstName", previous, firstName);
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
String previous = this.lastName ;
this.lastName = lastName;
support.firePropertyChange("lastName", previous, lastName);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
}
public static void main(String[] args) {
launch(args);
}
}
使用适配器的解决方案class
请注意,在上面的示例中,编辑器中的文本字段不能直接使用 POJO class 的绑定(因为它不公开任何 JavaFX 属性);如果您想这样做,您可以为此目的创建更多 JavaBeanStringProperty
,但这最终会导致代码重复。如果您希望能够做到这一点,那么使用适配器 class 可能会有所帮助。以下是使用此解决方案时代码的样子。请注意,现在适配器 class 公开了 JavaFX 属性,因此 table 的单元格值工厂可以直接映射到这些属性:JavaBeanStringProperty
的创建被封装在一个地方(适配器 class):
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class PojoTable extends Application {
@Override
public void start(Stage primaryStage) {
TableView<PersonAdapter> table = new TableView<>();
table.setEditable(true);
TableColumn<PersonAdapter, String> firstNameColumn = createColumn("First Name", PersonAdapter::firstNameProperty);
TableColumn<PersonAdapter, String> lastNameColumn = createColumn("Last Name", PersonAdapter::lastNameProperty);
table.getColumns().add(firstNameColumn);
table.getColumns().add(lastNameColumn);
List<Person> data = Arrays.asList(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
Button button = new Button("Show data");
button.setOnAction(e -> {
data.stream().map(person -> person.getFirstName() + " " + person.getLastName())
.forEach(System.out::println);
System.out.println();
});
Button edit = new Button("Edit");
edit.disableProperty().bind(table.getSelectionModel().selectedItemProperty().isNull());
edit.setOnAction(e -> edit(table.getSelectionModel().getSelectedItem(), primaryStage));
data.stream().map(PersonAdapter::new).forEach(table.getItems()::add);
HBox buttons = new HBox(10, button, edit);
buttons.setAlignment(Pos.CENTER);
BorderPane root = new BorderPane(table, null, null, buttons, null);
BorderPane.setAlignment(buttons, Pos.CENTER);
BorderPane.setMargin(buttons, new Insets(10));
root.setPadding(new Insets(10));
primaryStage.setScene(new Scene(root, 600, 600));
primaryStage.show();
}
private void edit(PersonAdapter person, Stage primaryStage) {
GridPane editPane = new GridPane();
TextField firstNameField = new TextField();
firstNameField.textProperty().bindBidirectional(person.firstNameProperty());
TextField lastNameField = new TextField();
lastNameField.textProperty().bindBidirectional(person.lastNameProperty());
Button okButton = new Button("OK");
HBox buttons = new HBox(10, okButton);
editPane.addRow(0, new Label("First Name:"), firstNameField);
editPane.addRow(1, new Label("Last Name:"), lastNameField);
editPane.add(buttons, 0, 2, 2, 1);
GridPane.setHalignment(buttons, HPos.CENTER);
GridPane.setMargin(buttons, new Insets(10));
editPane.setPadding(new Insets(10));
Scene scene = new Scene(editPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.initOwner(primaryStage);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
okButton.setOnAction(e -> {
stage.hide();
});
stage.show();
}
private TableColumn<PersonAdapter, String> createColumn(String title, Function<PersonAdapter, StringProperty> property) {
TableColumn<PersonAdapter, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setCellFactory(TextFieldTableCell.forTableColumn());
return col ;
}
public static class Person {
private String firstName ;
private String lastName ;
private PropertyChangeSupport support ;
public Person(String firstName, String lastName) {
this.firstName = firstName ;
this.lastName = lastName ;
support = new PropertyChangeSupport(this);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
String previous = this.firstName ;
this.firstName = firstName;
support.firePropertyChange("firstName", previous, firstName);
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
String previous = this.lastName ;
this.lastName = lastName;
support.firePropertyChange("lastName", previous, lastName);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
}
public static class PersonAdapter {
private final Person person ;
private final StringProperty firstName ;
private final StringProperty lastName ;
public PersonAdapter(Person person) {
this.person = person ;
try {
this.firstName = new JavaBeanStringPropertyBuilder()
.bean(person)
.name("firstName")
.build();
this.lastName = new JavaBeanStringPropertyBuilder()
.bean(person)
.name("lastName")
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Person getPerson() {
return person ;
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final String lastName) {
this.lastNameProperty().set(lastName);
}
}
public static void main(String[] args) {
launch(args);
}
}
这种方法的一个可能缺点是对基础列表的更改(简单示例中的 data
)不会传播到 table(这意味着从 [= 添加或删除元素17=] 不会更改 table;对 table 的现有元素调用 setFirstName
或 setLastName
将允许更新)。有关管理此问题的技术,请参阅
对于 DTO,我使用 POJO。因此,为了进行双向绑定,我创建了适配器。我的意思是,类似的东西:
POJO:
public class Temp{
private BigDecimal weight;
private final PropertyChangeSupport propertyChangeSupport;
public Temp() {
this.propertyChangeSupport = new PropertyChangeSupport(this);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
public BigDecimal getWeight() {
return weight;
}
public void setWeight(BigDecimal weight) {
BigDecimal pv = this.weight;
this.weight = weight;
propertyChangeSupport.firePropertyChange("weight", pv, weight);
}
}
我有以下适配器:
public class TempAdapter {
private ObjectProperty<BigDecimal> weightProperty;
public TempAdapter(Temp temp) {
try {
weightProperty=new JavaBeanObjectPropertyBuilder<BigDecimal>().bean(temp).name("weight").build();
weightProperty.addListener(new ChangeListener<BigDecimal>() {
@Override
public void changed(ObservableValue<? extends BigDecimal> ov, BigDecimal t, BigDecimal t1) {
....
}
});
} catch (NoSuchMethodException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
}
public ObjectProperty<BigDecimal> getWeightProperty() {
return weightProperty;
}
但是,我不明白如何将此适配器与 TableView 一起使用。我想为 TableView 使用适配器的原因是,如果我们将 POJO 用于带有 TableView 的 DTO,我们将不得不在 TableView 中复制适配器的代码。
据我所知,对于 TableView 中的每一行,我们都必须创建一个新的适配器实例,但我不知道该怎么做。
没有适配器的解决方案class
首先请注意,您不一定需要适配器 class;您可以只在需要的地方创建 JavaBeanProperty
个实例:在本例中是在 table 的单元格值工厂中。如果 UI 中只有一个(或两个)位置需要直接绑定到与 POJO 中的属性相对应的 JavaFX 属性,那么这可能是要走的路。
这是此技术的完整示例,使用的是常用的 Oracle Person
table 示例。在此示例中,没有适配器 class:table 只是在单元格值工厂中创建了 JavaBeanStringProperty
适配器。有一个编辑表单,它直接与 POJO class 交互。
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javafx.application.Application;
import javafx.beans.property.adapter.JavaBeanStringProperty;
import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class PojoTable extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Person> table = new TableView<>();
table.setEditable(true);
TableColumn<Person, String> firstNameColumn = createColumn("First Name", "firstName");
TableColumn<Person, String> lastNameColumn = createColumn("Last Name", "lastName");
table.getColumns().add(firstNameColumn);
table.getColumns().add(lastNameColumn);
Button button = new Button("Show data");
button.setOnAction(e -> {
table.getItems().stream().map(person -> person.getFirstName() + " " + person.getLastName())
.forEach(System.out::println);
System.out.println();
});
Button edit = new Button("Edit");
edit.disableProperty().bind(table.getSelectionModel().selectedItemProperty().isNull());
edit.setOnAction(e -> edit(table.getSelectionModel().getSelectedItem(), primaryStage));
table.getItems().addAll(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
HBox buttons = new HBox(10, button, edit);
buttons.setAlignment(Pos.CENTER);
BorderPane root = new BorderPane(table, null, null, buttons, null);
BorderPane.setAlignment(buttons, Pos.CENTER);
BorderPane.setMargin(buttons, new Insets(10));
root.setPadding(new Insets(10));
primaryStage.setScene(new Scene(root, 600, 600));
primaryStage.show();
}
private void edit(Person person, Stage primaryStage) {
GridPane editPane = new GridPane();
TextField firstNameField = new TextField(person.getFirstName());
TextField lastNameField = new TextField(person.getLastName());
Button okButton = new Button("OK");
Button cancelButton = new Button("Cancel");
HBox buttons = new HBox(10, okButton, cancelButton);
editPane.addRow(0, new Label("First Name:"), firstNameField);
editPane.addRow(1, new Label("Last Name:"), lastNameField);
editPane.add(buttons, 0, 2, 2, 1);
GridPane.setHalignment(buttons, HPos.CENTER);
GridPane.setMargin(buttons, new Insets(10));
editPane.setPadding(new Insets(10));
Scene scene = new Scene(editPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.initOwner(primaryStage);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
cancelButton.setOnAction(e -> stage.hide());
okButton.setOnAction(e -> {
person.setFirstName(firstNameField.getText());
person.setLastName(lastNameField.getText());
stage.hide();
});
stage.show();
}
private TableColumn<Person, String> createColumn(String title, String property) {
TableColumn<Person, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> {
Person p = cellData.getValue();
try {
JavaBeanStringProperty prop = new JavaBeanStringPropertyBuilder()
.bean(p)
.name(property)
.build();
return prop;
} catch (Exception e) {
throw new RuntimeException(e);
}
});
col.setCellFactory(TextFieldTableCell.forTableColumn());
return col ;
}
public static class Person {
private String firstName ;
private String lastName ;
private PropertyChangeSupport support ;
public Person(String firstName, String lastName) {
this.firstName = firstName ;
this.lastName = lastName ;
support = new PropertyChangeSupport(this);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
String previous = this.firstName ;
this.firstName = firstName;
support.firePropertyChange("firstName", previous, firstName);
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
String previous = this.lastName ;
this.lastName = lastName;
support.firePropertyChange("lastName", previous, lastName);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
}
public static void main(String[] args) {
launch(args);
}
}
使用适配器的解决方案class
请注意,在上面的示例中,编辑器中的文本字段不能直接使用 POJO class 的绑定(因为它不公开任何 JavaFX 属性);如果您想这样做,您可以为此目的创建更多 JavaBeanStringProperty
,但这最终会导致代码重复。如果您希望能够做到这一点,那么使用适配器 class 可能会有所帮助。以下是使用此解决方案时代码的样子。请注意,现在适配器 class 公开了 JavaFX 属性,因此 table 的单元格值工厂可以直接映射到这些属性:JavaBeanStringProperty
的创建被封装在一个地方(适配器 class):
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import javafx.application.Application;
import javafx.beans.property.StringProperty;
import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class PojoTable extends Application {
@Override
public void start(Stage primaryStage) {
TableView<PersonAdapter> table = new TableView<>();
table.setEditable(true);
TableColumn<PersonAdapter, String> firstNameColumn = createColumn("First Name", PersonAdapter::firstNameProperty);
TableColumn<PersonAdapter, String> lastNameColumn = createColumn("Last Name", PersonAdapter::lastNameProperty);
table.getColumns().add(firstNameColumn);
table.getColumns().add(lastNameColumn);
List<Person> data = Arrays.asList(
new Person("Jacob", "Smith"),
new Person("Isabella", "Johnson"),
new Person("Ethan", "Williams"),
new Person("Emma", "Jones"),
new Person("Michael", "Brown")
);
Button button = new Button("Show data");
button.setOnAction(e -> {
data.stream().map(person -> person.getFirstName() + " " + person.getLastName())
.forEach(System.out::println);
System.out.println();
});
Button edit = new Button("Edit");
edit.disableProperty().bind(table.getSelectionModel().selectedItemProperty().isNull());
edit.setOnAction(e -> edit(table.getSelectionModel().getSelectedItem(), primaryStage));
data.stream().map(PersonAdapter::new).forEach(table.getItems()::add);
HBox buttons = new HBox(10, button, edit);
buttons.setAlignment(Pos.CENTER);
BorderPane root = new BorderPane(table, null, null, buttons, null);
BorderPane.setAlignment(buttons, Pos.CENTER);
BorderPane.setMargin(buttons, new Insets(10));
root.setPadding(new Insets(10));
primaryStage.setScene(new Scene(root, 600, 600));
primaryStage.show();
}
private void edit(PersonAdapter person, Stage primaryStage) {
GridPane editPane = new GridPane();
TextField firstNameField = new TextField();
firstNameField.textProperty().bindBidirectional(person.firstNameProperty());
TextField lastNameField = new TextField();
lastNameField.textProperty().bindBidirectional(person.lastNameProperty());
Button okButton = new Button("OK");
HBox buttons = new HBox(10, okButton);
editPane.addRow(0, new Label("First Name:"), firstNameField);
editPane.addRow(1, new Label("Last Name:"), lastNameField);
editPane.add(buttons, 0, 2, 2, 1);
GridPane.setHalignment(buttons, HPos.CENTER);
GridPane.setMargin(buttons, new Insets(10));
editPane.setPadding(new Insets(10));
Scene scene = new Scene(editPane);
Stage stage = new Stage();
stage.setScene(scene);
stage.initOwner(primaryStage);
stage.initModality(Modality.APPLICATION_MODAL);
stage.initStyle(StageStyle.UNDECORATED);
okButton.setOnAction(e -> {
stage.hide();
});
stage.show();
}
private TableColumn<PersonAdapter, String> createColumn(String title, Function<PersonAdapter, StringProperty> property) {
TableColumn<PersonAdapter, String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setCellFactory(TextFieldTableCell.forTableColumn());
return col ;
}
public static class Person {
private String firstName ;
private String lastName ;
private PropertyChangeSupport support ;
public Person(String firstName, String lastName) {
this.firstName = firstName ;
this.lastName = lastName ;
support = new PropertyChangeSupport(this);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
String previous = this.firstName ;
this.firstName = firstName;
support.firePropertyChange("firstName", previous, firstName);
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
String previous = this.lastName ;
this.lastName = lastName;
support.firePropertyChange("lastName", previous, lastName);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
}
public static class PersonAdapter {
private final Person person ;
private final StringProperty firstName ;
private final StringProperty lastName ;
public PersonAdapter(Person person) {
this.person = person ;
try {
this.firstName = new JavaBeanStringPropertyBuilder()
.bean(person)
.name("firstName")
.build();
this.lastName = new JavaBeanStringPropertyBuilder()
.bean(person)
.name("lastName")
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Person getPerson() {
return person ;
}
public final StringProperty firstNameProperty() {
return this.firstName;
}
public final String getFirstName() {
return this.firstNameProperty().get();
}
public final void setFirstName(final String firstName) {
this.firstNameProperty().set(firstName);
}
public final StringProperty lastNameProperty() {
return this.lastName;
}
public final String getLastName() {
return this.lastNameProperty().get();
}
public final void setLastName(final String lastName) {
this.lastNameProperty().set(lastName);
}
}
public static void main(String[] args) {
launch(args);
}
}
这种方法的一个可能缺点是对基础列表的更改(简单示例中的 data
)不会传播到 table(这意味着从 [= 添加或删除元素17=] 不会更改 table;对 table 的现有元素调用 setFirstName
或 setLastName
将允许更新)。有关管理此问题的技术,请参阅