用于编辑表的 javafx 绑定代码片段对我不起作用
javafx binding for edit tables Code snippet doesn't work for me
我使用此代码片段完成了 table 的编辑提交。
UITableView - Better Editing through Binding?
我的问题是我得到一个
Caused by: java.lang.ClassCastException: javafx.beans.property.ReadOnlyObjectWrapper cannot be cast to javafx.beans.property.SimpleStringProperty
在这一行中:
SimpleStringProperty sp = (SimpleStringProperty)ov;
我不知道我能做些什么。
我的数据仅使用 SimpleStringProperty 值 class.
完整代码如下:
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextArea;
import javafx.util.Callback;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Supermain extends Application {
@Override
public void start(Stage primaryStage) {
final TableView<myTextRow> table = new TableView<>();
table.setEditable(true);
table.setStyle("-fx-text-wrap: true;");
//Table columns
TableColumn<myTextRow, String> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(new PropertyValueFactory<>("ID"));
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(new PropertyValueFactory<>("text"));
clmtext.setCellFactory(new TextFieldCellFactory());
//Add data
final ObservableList<myTextRow> data = FXCollections.observableArrayList(
new myTextRow(5, "Lorem"),
new myTextRow(2, "Ipsum")
);
table.setItems(data);
table.getColumns().addAll(clmID, clmtext);
HBox hBox = new HBox();
hBox.setSpacing(5.0);
hBox.setPadding(new Insets(5, 5, 5, 5));
Button btn = new Button();
btn.setText("Get Data");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
for (myTextRow data1 : data) {
System.out.println("data:"+data1.getText());
}
}
});
hBox.getChildren().add(btn);
BorderPane pane = new BorderPane();
pane.setTop(hBox);
pane.setCenter(table);
primaryStage.setScene(new Scene(pane, 640, 480));
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public static class TextFieldCellFactory
implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> {
@Override
public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) {
TextFieldCell textFieldCell = new TextFieldCell();
return textFieldCell;
}
public static class TextFieldCell extends TableCell<myTextRow, String> {
private TextArea textField;
private StringProperty boundToCurrently = null;
public TextFieldCell() {
String strCss;
// Padding in Text field cell is not wanted - we want the Textfield itself to "be"
// The cell. Though, this is aesthetic only. to each his own. comment out
// to revert back.
strCss = "-fx-padding: 0;";
this.setStyle(strCss);
textField = new TextArea();
textField.setWrapText(true);
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
//textField.setPrefHeight(real_lines_height(textField.getText(),this.getWidth(),30,23));
//
// Default style pulled from caspian.css. Used to play around with the inset background colors
// ---trying to produce a text box without borders
strCss = ""
+ //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" +
"-fx-background-color: -fx-control-inner-background;"
+ //"-fx-background-insets: 0, 1, 2;" +
"-fx-background-insets: 0;"
+ //"-fx-background-radius: 3, 2, 2;" +
"-fx-background-radius: 0;"
+ // "-fx-padding: 3 5 3 5;" + /*Play with this value to center the text depending on cell height??*/
"-fx-padding: 0 0 0 0;"
+ /*Play with this value to center the text depending on cell height??*/ //"-fx-padding: 0 0 0 0;" +
"-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);"
+ "-fx-cursor: text;"
+ "";
// Focused and hover states should be set in the CSS. This is just a test
// to see what happens when we set the style in code
textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
TextArea tf = (TextArea) getGraphic();
// System.out.println(".changed() index : "+ get_ID_from_table_index(getIndex()));
String strStyleGotFocus = "-fx-background-color: blue, -fx-text-box-border, -fx-control-inner-background;"
+ "-fx-background-insets: -0.4, 1, 2;"
+ "-fx-background-radius: 3.4, 2, 2;";
String strStyleLostFocus
= //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" +
"-fx-background-color: -fx-control-inner-background;"
+ //"-fx-background-insets: 0, 1, 2;" +
"-fx-background-insets: 0;"
+ //"-fx-background-radius: 3, 2, 2;" +
"-fx-background-radius: 0;"
+ //"-fx-padding: 3 5 3 5;" + /**/
"-fx-padding: 0 0 0 0;"
+ /**/ //"-fx-padding: 0 0 0 0;" +
"-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);"
+ "-fx-cursor: text;"
+ "";
if (newValue.booleanValue()) {
tf.setStyle(strStyleGotFocus);
} else {
tf.setStyle(strStyleLostFocus);
}
if(!newValue)
{
System.out.println("EDITABLE???? "+isEditing());
System.out.println("TEXT:::: "+textField.getText());
// commitEdit(textField.getText());
}
}
});
textField.hoverProperty().addListener(new ChangeListener<Boolean>() {
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
TextArea tf = (TextArea) getGraphic();
String strStyleGotHover = "-fx-background-color: derive(blue,90%), -fx-text-box-border, derive(-fx-control-inner-background, 10%);"
+ "-fx-background-insets: 1, 2.8, 3.8;"
+ "-fx-background-radius: 3.4, 2, 2;";
String strStyleLostHover
= //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" +
"-fx-background-color: -fx-control-inner-background;"
+ //"-fx-background-insets: 0, 1, 2;" +
"-fx-background-insets: 0;"
+ //"-fx-background-radius: 3, 2, 2;" +
"-fx-background-radius: 0;"
+ //"-fx-padding: 3 5 3 5;" + /**/
"-fx-padding: 0 0 0 0;"
+ "-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);"
+ "-fx-cursor: text;"
+ "";
String strStyleHasFocus = "-fx-background-color: blue, -fx-text-box-border, -fx-control-inner-background;"
+ "-fx-background-insets: -0.4, 1, 2;"
+ "-fx-background-radius: 3.4, 2, 2;";
if (newValue.booleanValue()) {
tf.setStyle(strStyleGotHover);
} else if (!tf.focusedProperty().get()) {
tf.setStyle(strStyleLostHover);
} else {
tf.setStyle(strStyleHasFocus);
}
}
});
textField.textProperty().addListener(e -> {
double height = 25;
textField.setPrefHeight(height);
textField.setMaxHeight(height);
//System.out.println("textfield Parent: "+textField.getParent().toString());
});
textField.setStyle(strCss);
this.setGraphic(textField);
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if(!empty) {
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// Retrieve the actual String Property that should be bound to the TextField
// If the TextField is currently bound to a different StringProperty
// Unbind the old property and rebind to the new one
ObservableValue<String> ov = getTableColumn().getCellObservableValue(getIndex());
SimpleStringProperty sp = (SimpleStringProperty)ov;
if(this.boundToCurrently==null) {
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(sp);
}
else {
if(this.boundToCurrently != sp) {
this.textField.textProperty().unbindBidirectional(this.boundToCurrently);
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(this.boundToCurrently);
}
}
System.out.println("item=" + item + " ObservableValue<String>=" + ov.getValue());
//this.textField.setText(item); // No longer need this!!!
}
else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
}
public class myTextRow {
private final SimpleIntegerProperty ID;
private final SimpleStringProperty text;
public myTextRow(int ID, String text) {
this.ID = new SimpleIntegerProperty(ID);
this.text = new SimpleStringProperty(text);
}
public void setID(int id) {
this.ID.set(id);
}
public void setText(String text) {
this.text.set(text);
}
public int getID() {
return ID.get();
}
public String getText() {
return text.get();
}
}
}
您的模型 class 缺少 "property accessors"。因此,属性本身不能被 PropertyValueFactory
使用。如 PropertyValueFactory
documentation 中所述:
An example of how to use this class is:
TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name");
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
In this example,
the "firstName"
string is used as a reference to an assumed
firstNameProperty()
method in the Person
class type (which is the
class type of the TableView
items list). Additionally, this method
must return a Property instance. If a method meeting these
requirements is found, then the TableCell is populated with this
ObservableValue. In addition, the TableView will automatically add an
observer to the returned value, such that any changes fired will be
observed by the TableView, resulting in the cell immediately updating.
If no method matching this pattern exists, there is fall-through
support for attempting to call get() or is() (that
is, getFirstName()
or isFirstName()
in the example above). If a method
matching this pattern exists, the value returned from this method is
wrapped in a ReadOnlyObjectWrapper
and returned to the TableCell
.
最后一段准确描述了您的情况,因为您的模型 class 中没有定义 textProperty()
或 iDProperty()
方法。因此 PropertyValueFactory
为你创建了一个 ReadOnlyObjectWrapper
并且 returns 它,而不是返回实际的 属性 实例。
另请注意,您的 id 列类型有误。 属性 是 IntegerProperty
,它是 Property<Number>
,而不是 Property<String>
。因此,table 列需要是 TableColumn<myTextRow, Number>
。这将使使用 table 单元格实现变得相当棘手,因为您需要在文本字段中的字符串和作为 id
.
值的整数之间进行转换
不过一般来说,在JavaFX Property pattern之后写class如下:
public class myTextRow {
private final IntegerProperty id;
private final StringProperty text;
public myTextRow(int ID, String text) {
this.id = new SimpleIntegerProperty(ID);
this.text = new SimpleStringProperty(text);
}
public void setId(int id) {
this.id.set(id);
}
public void setText(String text) {
this.text.set(text);
}
public int getId() {
return id.get();
}
public String getText() {
return text.get();
}
public StringProperty textProperty() {
return text;
}
public IntegerProperty idProperty() {
return id ;
}
}
然后您可以将单元格值工厂定义为
TableColumn<myTextRow, Number> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(new PropertyValueFactory<>("id"));
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(new PropertyValueFactory<>("text"));
或者,使用 lambda 表达式(这使得代码类型安全并允许编译器检查是否存在正确的方法):
TableColumn<myTextRow, Number> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(cellData -> cellData.getValue().idProperty());
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(cellData -> cellData.getValue().textProperty());
我使用此代码片段完成了 table 的编辑提交。 UITableView - Better Editing through Binding?
我的问题是我得到一个
Caused by: java.lang.ClassCastException: javafx.beans.property.ReadOnlyObjectWrapper cannot be cast to javafx.beans.property.SimpleStringProperty
在这一行中:
SimpleStringProperty sp = (SimpleStringProperty)ov;
我不知道我能做些什么。 我的数据仅使用 SimpleStringProperty 值 class.
完整代码如下:
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextArea;
import javafx.util.Callback;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Supermain extends Application {
@Override
public void start(Stage primaryStage) {
final TableView<myTextRow> table = new TableView<>();
table.setEditable(true);
table.setStyle("-fx-text-wrap: true;");
//Table columns
TableColumn<myTextRow, String> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(new PropertyValueFactory<>("ID"));
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(new PropertyValueFactory<>("text"));
clmtext.setCellFactory(new TextFieldCellFactory());
//Add data
final ObservableList<myTextRow> data = FXCollections.observableArrayList(
new myTextRow(5, "Lorem"),
new myTextRow(2, "Ipsum")
);
table.setItems(data);
table.getColumns().addAll(clmID, clmtext);
HBox hBox = new HBox();
hBox.setSpacing(5.0);
hBox.setPadding(new Insets(5, 5, 5, 5));
Button btn = new Button();
btn.setText("Get Data");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
for (myTextRow data1 : data) {
System.out.println("data:"+data1.getText());
}
}
});
hBox.getChildren().add(btn);
BorderPane pane = new BorderPane();
pane.setTop(hBox);
pane.setCenter(table);
primaryStage.setScene(new Scene(pane, 640, 480));
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public static class TextFieldCellFactory
implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> {
@Override
public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) {
TextFieldCell textFieldCell = new TextFieldCell();
return textFieldCell;
}
public static class TextFieldCell extends TableCell<myTextRow, String> {
private TextArea textField;
private StringProperty boundToCurrently = null;
public TextFieldCell() {
String strCss;
// Padding in Text field cell is not wanted - we want the Textfield itself to "be"
// The cell. Though, this is aesthetic only. to each his own. comment out
// to revert back.
strCss = "-fx-padding: 0;";
this.setStyle(strCss);
textField = new TextArea();
textField.setWrapText(true);
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
//textField.setPrefHeight(real_lines_height(textField.getText(),this.getWidth(),30,23));
//
// Default style pulled from caspian.css. Used to play around with the inset background colors
// ---trying to produce a text box without borders
strCss = ""
+ //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" +
"-fx-background-color: -fx-control-inner-background;"
+ //"-fx-background-insets: 0, 1, 2;" +
"-fx-background-insets: 0;"
+ //"-fx-background-radius: 3, 2, 2;" +
"-fx-background-radius: 0;"
+ // "-fx-padding: 3 5 3 5;" + /*Play with this value to center the text depending on cell height??*/
"-fx-padding: 0 0 0 0;"
+ /*Play with this value to center the text depending on cell height??*/ //"-fx-padding: 0 0 0 0;" +
"-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);"
+ "-fx-cursor: text;"
+ "";
// Focused and hover states should be set in the CSS. This is just a test
// to see what happens when we set the style in code
textField.focusedProperty().addListener(new ChangeListener<Boolean>() {
@Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
TextArea tf = (TextArea) getGraphic();
// System.out.println(".changed() index : "+ get_ID_from_table_index(getIndex()));
String strStyleGotFocus = "-fx-background-color: blue, -fx-text-box-border, -fx-control-inner-background;"
+ "-fx-background-insets: -0.4, 1, 2;"
+ "-fx-background-radius: 3.4, 2, 2;";
String strStyleLostFocus
= //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" +
"-fx-background-color: -fx-control-inner-background;"
+ //"-fx-background-insets: 0, 1, 2;" +
"-fx-background-insets: 0;"
+ //"-fx-background-radius: 3, 2, 2;" +
"-fx-background-radius: 0;"
+ //"-fx-padding: 3 5 3 5;" + /**/
"-fx-padding: 0 0 0 0;"
+ /**/ //"-fx-padding: 0 0 0 0;" +
"-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);"
+ "-fx-cursor: text;"
+ "";
if (newValue.booleanValue()) {
tf.setStyle(strStyleGotFocus);
} else {
tf.setStyle(strStyleLostFocus);
}
if(!newValue)
{
System.out.println("EDITABLE???? "+isEditing());
System.out.println("TEXT:::: "+textField.getText());
// commitEdit(textField.getText());
}
}
});
textField.hoverProperty().addListener(new ChangeListener<Boolean>() {
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
TextArea tf = (TextArea) getGraphic();
String strStyleGotHover = "-fx-background-color: derive(blue,90%), -fx-text-box-border, derive(-fx-control-inner-background, 10%);"
+ "-fx-background-insets: 1, 2.8, 3.8;"
+ "-fx-background-radius: 3.4, 2, 2;";
String strStyleLostHover
= //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" +
"-fx-background-color: -fx-control-inner-background;"
+ //"-fx-background-insets: 0, 1, 2;" +
"-fx-background-insets: 0;"
+ //"-fx-background-radius: 3, 2, 2;" +
"-fx-background-radius: 0;"
+ //"-fx-padding: 3 5 3 5;" + /**/
"-fx-padding: 0 0 0 0;"
+ "-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);"
+ "-fx-cursor: text;"
+ "";
String strStyleHasFocus = "-fx-background-color: blue, -fx-text-box-border, -fx-control-inner-background;"
+ "-fx-background-insets: -0.4, 1, 2;"
+ "-fx-background-radius: 3.4, 2, 2;";
if (newValue.booleanValue()) {
tf.setStyle(strStyleGotHover);
} else if (!tf.focusedProperty().get()) {
tf.setStyle(strStyleLostHover);
} else {
tf.setStyle(strStyleHasFocus);
}
}
});
textField.textProperty().addListener(e -> {
double height = 25;
textField.setPrefHeight(height);
textField.setMaxHeight(height);
//System.out.println("textfield Parent: "+textField.getParent().toString());
});
textField.setStyle(strCss);
this.setGraphic(textField);
}
@Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if(!empty) {
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// Retrieve the actual String Property that should be bound to the TextField
// If the TextField is currently bound to a different StringProperty
// Unbind the old property and rebind to the new one
ObservableValue<String> ov = getTableColumn().getCellObservableValue(getIndex());
SimpleStringProperty sp = (SimpleStringProperty)ov;
if(this.boundToCurrently==null) {
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(sp);
}
else {
if(this.boundToCurrently != sp) {
this.textField.textProperty().unbindBidirectional(this.boundToCurrently);
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(this.boundToCurrently);
}
}
System.out.println("item=" + item + " ObservableValue<String>=" + ov.getValue());
//this.textField.setText(item); // No longer need this!!!
}
else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
}
public class myTextRow {
private final SimpleIntegerProperty ID;
private final SimpleStringProperty text;
public myTextRow(int ID, String text) {
this.ID = new SimpleIntegerProperty(ID);
this.text = new SimpleStringProperty(text);
}
public void setID(int id) {
this.ID.set(id);
}
public void setText(String text) {
this.text.set(text);
}
public int getID() {
return ID.get();
}
public String getText() {
return text.get();
}
}
}
您的模型 class 缺少 "property accessors"。因此,属性本身不能被 PropertyValueFactory
使用。如 PropertyValueFactory
documentation 中所述:
An example of how to use this class is:
TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name"); firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName"));
In this example, the
"firstName"
string is used as a reference to an assumedfirstNameProperty()
method in thePerson
class type (which is the class type of theTableView
items list). Additionally, this method must return a Property instance. If a method meeting these requirements is found, then the TableCell is populated with this ObservableValue. In addition, the TableView will automatically add an observer to the returned value, such that any changes fired will be observed by the TableView, resulting in the cell immediately updating.If no method matching this pattern exists, there is fall-through support for attempting to call get() or is() (that is,
getFirstName()
orisFirstName()
in the example above). If a method matching this pattern exists, the value returned from this method is wrapped in aReadOnlyObjectWrapper
and returned to theTableCell
.
最后一段准确描述了您的情况,因为您的模型 class 中没有定义 textProperty()
或 iDProperty()
方法。因此 PropertyValueFactory
为你创建了一个 ReadOnlyObjectWrapper
并且 returns 它,而不是返回实际的 属性 实例。
另请注意,您的 id 列类型有误。 属性 是 IntegerProperty
,它是 Property<Number>
,而不是 Property<String>
。因此,table 列需要是 TableColumn<myTextRow, Number>
。这将使使用 table 单元格实现变得相当棘手,因为您需要在文本字段中的字符串和作为 id
.
不过一般来说,在JavaFX Property pattern之后写class如下:
public class myTextRow {
private final IntegerProperty id;
private final StringProperty text;
public myTextRow(int ID, String text) {
this.id = new SimpleIntegerProperty(ID);
this.text = new SimpleStringProperty(text);
}
public void setId(int id) {
this.id.set(id);
}
public void setText(String text) {
this.text.set(text);
}
public int getId() {
return id.get();
}
public String getText() {
return text.get();
}
public StringProperty textProperty() {
return text;
}
public IntegerProperty idProperty() {
return id ;
}
}
然后您可以将单元格值工厂定义为
TableColumn<myTextRow, Number> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(new PropertyValueFactory<>("id"));
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(new PropertyValueFactory<>("text"));
或者,使用 lambda 表达式(这使得代码类型安全并允许编译器检查是否存在正确的方法):
TableColumn<myTextRow, Number> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(cellData -> cellData.getValue().idProperty());
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(cellData -> cellData.getValue().textProperty());