问题
Looking for help in diagnosing a behavior, as I'm at a loss for where it may be occurring.
On table edit, the labels update, but the values don't ever seem to, as whenever the table is updated the values revert. This happens with sorting, and can be shown to be true via:
for(Row r : elementsTable.getItems().get(0))
System.out.println(r.getSymbol() + r.getWeight() + r.getAtom());
GUI:
@FXML
private TextField row1;
@FXML
private TextField row2;
@FXML
private TextField row3;
@FXML
private TableView<Row> elementsTable;
private List<Row> row;
private ObservableList<Row> oRow;
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
row = new ArrayList();
}
private void addRow(ActionEvent event) {
elementsTable.getItems().add(new Row(
row1.getText(),
row2.getText(),
row3.getText()));
}
public void
construct(List<String> z, List<String> w, List<String> z)
throws Exception{
//populate table rows
for(int i = 0; i < z.size(); i++){
row.add(new Row(z.get(i), w.get(i), a.get(i)));
}
oRow = FXCollections.observableArrayList(row);
elementsTable.setItems(oRow);
}
FXML
<TableView fx:id="elementsTable" editable="true" layoutX="67.0" layoutY="124.0" prefHeight="237.0" prefWidth="523.0">
<columns>
<TableColumn fx:id="elementCol" editable="true" prefWidth="138.0" text="Element">
<cellFactory>
<TextFieldTableCell fx:factory="forTableColumn" />
</cellFactory>
<cellValueFactory>
<PropertyValueFactory property="symbol" />
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="weightCol" editable="true" prefWidth="191.0" text="Weight Fraction">
<cellFactory>
<TextFieldTableCell fx:factory="forTableColumn" />
</cellFactory>
<cellValueFactory>
<PropertyValueFactory property="weight" />
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="atomCol" editable="true" prefWidth="189.0" text="Atom Fraction">
<cellFactory>
<TextFieldTableCell fx:factory="forTableColumn" />
</cellFactory>
<cellValueFactory>
<PropertyValueFactory property="atom" />
</cellValueFactory>
</TableColumn>
</columns>
<items>
<FXCollections fx:factory="observableArrayList">
<Row atom="" symbol="" weight="" />
</FXCollections>
</items>
</TableView>
Table model
public class Row{
private final SimpleStringProperty symbol = new SimpleStringProperty("");
private final SimpleStringProperty weight = new SimpleStringProperty("");
private final SimpleStringProperty atom = new SimpleStringProperty("");
/**
* Default constructor, defaults to empty strings
*/
public Row(){
this("","","");
}
/**
*
* @param s symbol(or ZA)
* @param w weight fraction
* @param a atom fraction (or atom count ending with "#")
*/
public Row(String s, String w, String a){
setSymbol(s);
setWeight(w);
setAtom(a);
}
public String getSymbol(){return symbol.get();}
public String getWeight(){return weight.get();}
public String getAtom(){return atom.get();}
public void setSymbol(String s){symbol.set(s);}
public void setWeight(String w){weight.set(w);}
public void setAtom(String a){atom.set(a);}
}
State 1: before doing anything

State 2: edited cells

State 3: adding row to table, data reverts edits

回答1:
The issue is that you don't provide "property accessor" methods in your Row
class. Without these, the PropertyValueFactory
and the TextFieldTableCell
cannot access the actual properties and bind/listen to them for changes.So your Row
class should look like
public class Row{
private final SimpleStringProperty symbol = new SimpleStringProperty("");
private final SimpleStringProperty weight = new SimpleStringProperty("");
private final SimpleStringProperty atom = new SimpleStringProperty("");
/**
* Default constructor, defaults to empty strings
*/
public Row(){
this("","","");
}
/**
*
* @param s symbol(or ZA)
* @param w weight fraction
* @param a atom fraction (or atom count ending with "#")
*/
public Row(String s, String w, String a){
setSymbol(s);
setWeight(w);
setAtom(a);
}
public String getSymbol(){return symbol.get();}
public String getWeight(){return weight.get();}
public String getAtom(){return atom.get();}
public void setSymbol(String s){symbol.set(s);}
public void setWeight(String w){weight.set(w);}
public void setAtom(String a){atom.set(a);}
public StringProperty symbolProperty() {
return symbol ;
}
public StringProperty weightProperty() {
return weight ;
}
public StringProperty atomProperty() {
return atom ;
}
}
For more details, check the API documentation for PropertyValueFactory and the tutorial section on properties (which is just general background on the JavaFX property pattern).
If, for some reason, you can't provide these methods (e.g. you are using existing classes you cannot change as your model), you can provide the "wiring" between the table column editing and the model by hand, using TableColumn.setOnEditCommit(...)
in your controller class. The following should make things work with your existing Row
class, though I recommend implementing the model with the "property accessors" whenever possible.
public void initialize(URL url, ResourceBundle rb) {
// ...
elementCol.setOnEditCommit(e -> {
int rowIndex = e.getTablePosition().getRow();
Row row = elementsTable.getItems().get(rowIndex);
row.setElement(e.getNewValue());
});
// similarly for other columns...
}
来源:https://stackoverflow.com/questions/31269932/javafx-tableview-not-binding-reverting