JavaFX TableView可编辑单元格+编辑后更改样式
JavaFX TableView editable cell + change style after edit
我需要使 TableView 中的单元格可编辑,并在更改提交后将其设为粗体。我可以单独制作这些东西,但不能一起制作,因为它们是通过 setCellFactory 方法实现的。
以下是代码部分:
设置细胞工厂
((TableColumn) lpAttributesTable.getColumns().get(1)).setCellFactory(
new Callback<TableColumn<LPAttributesTableObject,String>, TableCell<LPAttributesTableObject,String>>() {
@Override
public TableCell<LPAttributesTableObject,String> call(
TableColumn<LPAttributesTableObject,String> param) {
TextFieldTableCell<LPAttributesTableObject, String> editableTableCell =
new TextFieldTableCell<LPAttributesTableObject, String>(new StringConverter<String>() {
@Override
public String toString(String object) {
return object;
}
@Override
public String fromString(String string) {
return string;
}
})
{
@Override
public void updateItem(String item, boolean empty)
{
super.updateItem(item,empty);
if (item == null || empty) {
setText(null);
// setStyle("");
}
else
{
setText(item);
styleProperty().bind(
Bindings.when(getTableRow().selectedProperty()).
then("-f-font-weight:bold;").otherwise(""));
}
}
};
return editableTableCell;
}
});
LPAttributesTable对象
public class LPAttributesTableObject {
private String attribute;
private String value;
public LPAttributesTableObject(String _attribute, String _value)
{
this.attribute = _attribute;
this.value = _value;
}
public final String getAttribute() { return attribute; }
public final String getValue() { return value; }
public StringProperty attributeProperty() { return new SimpleStringProperty(attribute); }
public StringProperty valueProperty() { return new SimpleStringProperty(value); }
public final void setAttribute(String _attr) { this.attribute = _attr;}
public final void setValue(String _description) { this.value = _description;}
}
Table 与模型绑定。请注意,我已经注释掉了仅编辑 cellFactory
((TableColumn) lpattrsTable.getColumns().get(1)).setCellValueFactory(new PropertyValueFactory<LPAttributesTableObject,String>("value"));
// ((TableColumn) lpattrsTable.getColumns().get(1)).setCellFactory(TextFieldTableCell.forTableColumn(new DefaultStringConverter()));
当前实现仅允许单元格编辑。
请注意,仅绑定到选定的 属性 是行不通的。您还需要保存该项目已被以某种方式编辑的事实。这可以使用项目的 属性 或 ObservableMap
.
来完成
此外,您还需要实际设置该项目已被编辑的信息。这可以通过覆盖 commitEdit
方法来完成。
// external storage of edited states by index
ObservableMap<Number, Boolean> edited = FXCollections.observableHashMap();
TableColumn<LPAttributesTableObject, String> column = (TableColumn) lpAttributesTable.getColumns().get(1);
StringConverter<String> converter = new DefaultStringConverter();
column.setCellFactory(t -> new TextFieldTableCell<LPAttributesTableObject, String>(converter) {
private final BooleanBinding editedBinding = Bindings.booleanValueAt(edited, indexProperty());
{
editedBinding.addListener((a, b, newValue) -> setStyle(newValue ? "-fx-font-weight:bold;" : ""));
}
@Override
public void commitEdit(String newValue) {
if (!Objects.equals(newValue, getItem())) {
// save data that this index has been edited
edited.put(getIndex(), Boolean.TRUE);
}
super.commitEdit(newValue);
}
});
请注意,如果 table 的项目列表被修改,您可能需要修改地图。
备选
使用存储项目是否被编辑的值类型而不是简单的 String
允许您保持代码简单,即使项目列表被修改:
public class EditableString {
private final boolean edited;
private final String value;
public EditableString(boolean edited, String value) {
this.edited = edited;
this.value = value;
}
public EditableString(String value) {
this(false, value);
}
public boolean isEdited() {
return edited;
}
public String getValue() {
return value;
}
}
StringConverter<EditableString> converter = new StringConverter<EditableString>() {
@Override
public String toString(EditableString object) {
return object == null ? null : object.getValue();
}
@Override
public EditableString fromString(String string) {
return string == null ? null : new EditableString(true, string);
}
};
TableColumn<LPAttributesTableObject, EditableString> column = (TableColumn) lpAttributesTable.getColumns().get(1);
column.setCellFactory(t -> new TextFieldTableCell<LPAttributesTableObject, EditableString>(converter) {
@Override
public void updateItem(EditableString item, boolean empty) {
super.updateItem(item, empty);
if (item != null && item.isEdited()) {
setStyle("-fx-font-weight: bold;");
} else {
setStyle("");
}
}
@Override
public void commitEdit(EditableString newValue) {
EditableString currentItem = getItem();
if (currentItem == null || newValue == null || !Objects.equals(newValue.getValue(), currentItem.getValue())) {
super.commitEdit(newValue);
} else {
// if the string is the same, keep the old value
super.commitEdit(currentItem);
}
}
});
请注意,这需要您将包含 String
的 LPAttributesTableObject
的 属性 更改为包含 EditableString
.[=19= 的 属性 ]
最后这就是我的意思。
StringConverter<EditableString> converter = new StringConverter<EditableString>() {
@Override
public String toString(EditableString object) {
System.out.println("bla bla");
return object == null ? null : object.toString();
}
@Override
public EditableString fromString(String string) {
System.out.println("bla");
return string == null ? null : new EditableString(true, string);
}
};
((TableColumn) lpAttributesTable.getColumns().get(1)).setCellValueFactory(new PropertyValueFactory<LPAttributesTableObject,EditableString>("val"));
((TableColumn) lpAttributesTable.getColumns().get(0)).setCellValueFactory(new PropertyValueFactory<LPAttributesTableObject,String>("attribute"));
TableColumn<LPAttributesTableObject, EditableString> col = (TableColumn) lpAttributesTable.getColumns().get(1);
col.setCellFactory(TextFieldTableCellEditable.<LPAttributesTableObject, EditableString>forTableColumn(converter));
我必须将现有的 TextFieldTableCell 对象扩展为:
public class TextFieldTableCellEditable<S,EditableString> extends TextFieldTableCell<S,EditableString> {
public static <S,EditableString> Callback<TableColumn<S,EditableString>, TableCell<S,EditableString>> forTableColumn(
final StringConverter<EditableString> converter) {
return list -> new TextFieldTableCellEditable<S, EditableString>(converter);
}
public TextFieldTableCellEditable(StringConverter<EditableString> converter) {
this.getStyleClass().add("text-field-table-cell");
setConverter(converter);
}
@Override
public final void updateItem(EditableString item, boolean empty) {
super.updateItem(item, empty);
if (item != null && ((sample.EditableString)item).isEdited()) {
setText(item.toString());
setStyle("-fx-font-weight: bold;");
} else if (item != null && !((sample.EditableString)item).isEdited()){
setStyle("");
setText(item.toString());
} else {
setStyle("");
setText(null);
}
}
@Override
public void commitEdit(EditableString newValue) {
EditableString currentItem = getItem();
if (currentItem == null || newValue == null || !Objects.equals(((sample.EditableString)newValue).getValue(), ((sample.EditableString)currentItem).getValue())) {
super.commitEdit(newValue);
} else {
// if the string is the same, keep the old value
super.commitEdit(currentItem);
}
}
}
LPAttributesTableObject 如下所示:
public class LPAttributesTableObject {
private String attribute;
private EditableString val;
public LPAttributesTableObject(String _attribute, EditableString _value)
{
this.attribute = _attribute;
this.val = _value;
}
public String getAttribute() { return attribute.toString(); }
public EditableString getVal() { return val; }
public final EditableString getValue() { return val; }
public StringProperty attributeProperty() { return new SimpleStringProperty(attribute.toString()); }
public ObjectProperty<EditableString> valProperty() { return new SimpleObjectProperty<EditableString>(this,"value",val); }
public void setAttribute(String _attr) { this.attribute = _attr;}
public void setValue(EditableString _value) { this.val = _value;}
public void setVal(EditableString _val) { this.val = _val; }
public void setVal(String _val) { this.val.setValue(_val);}
}
EditableString 看起来像这样:
public class EditableString {
private boolean edited;
private String string;
public EditableString(boolean edited, String val)
{
this.edited = edited;
this.string = val;
}
public EditableString(String val)
{
this.edited = false;
this.string = val;
}
public String getValue() { return string; }
public void setValue(String val) { this.string = val; }
public String toString() { return string; }
public boolean isEdited() { return edited; }
public void setValue(EditableString estr) { this.setValue(estr.getValue()); this.edited = estr.edited; }
}
我需要使 TableView 中的单元格可编辑,并在更改提交后将其设为粗体。我可以单独制作这些东西,但不能一起制作,因为它们是通过 setCellFactory 方法实现的。
以下是代码部分:
设置细胞工厂
((TableColumn) lpAttributesTable.getColumns().get(1)).setCellFactory(
new Callback<TableColumn<LPAttributesTableObject,String>, TableCell<LPAttributesTableObject,String>>() {
@Override
public TableCell<LPAttributesTableObject,String> call(
TableColumn<LPAttributesTableObject,String> param) {
TextFieldTableCell<LPAttributesTableObject, String> editableTableCell =
new TextFieldTableCell<LPAttributesTableObject, String>(new StringConverter<String>() {
@Override
public String toString(String object) {
return object;
}
@Override
public String fromString(String string) {
return string;
}
})
{
@Override
public void updateItem(String item, boolean empty)
{
super.updateItem(item,empty);
if (item == null || empty) {
setText(null);
// setStyle("");
}
else
{
setText(item);
styleProperty().bind(
Bindings.when(getTableRow().selectedProperty()).
then("-f-font-weight:bold;").otherwise(""));
}
}
};
return editableTableCell;
}
});
LPAttributesTable对象
public class LPAttributesTableObject {
private String attribute;
private String value;
public LPAttributesTableObject(String _attribute, String _value)
{
this.attribute = _attribute;
this.value = _value;
}
public final String getAttribute() { return attribute; }
public final String getValue() { return value; }
public StringProperty attributeProperty() { return new SimpleStringProperty(attribute); }
public StringProperty valueProperty() { return new SimpleStringProperty(value); }
public final void setAttribute(String _attr) { this.attribute = _attr;}
public final void setValue(String _description) { this.value = _description;}
}
Table 与模型绑定。请注意,我已经注释掉了仅编辑 cellFactory
((TableColumn) lpattrsTable.getColumns().get(1)).setCellValueFactory(new PropertyValueFactory<LPAttributesTableObject,String>("value"));
// ((TableColumn) lpattrsTable.getColumns().get(1)).setCellFactory(TextFieldTableCell.forTableColumn(new DefaultStringConverter()));
当前实现仅允许单元格编辑。
请注意,仅绑定到选定的 属性 是行不通的。您还需要保存该项目已被以某种方式编辑的事实。这可以使用项目的 属性 或 ObservableMap
.
此外,您还需要实际设置该项目已被编辑的信息。这可以通过覆盖 commitEdit
方法来完成。
// external storage of edited states by index
ObservableMap<Number, Boolean> edited = FXCollections.observableHashMap();
TableColumn<LPAttributesTableObject, String> column = (TableColumn) lpAttributesTable.getColumns().get(1);
StringConverter<String> converter = new DefaultStringConverter();
column.setCellFactory(t -> new TextFieldTableCell<LPAttributesTableObject, String>(converter) {
private final BooleanBinding editedBinding = Bindings.booleanValueAt(edited, indexProperty());
{
editedBinding.addListener((a, b, newValue) -> setStyle(newValue ? "-fx-font-weight:bold;" : ""));
}
@Override
public void commitEdit(String newValue) {
if (!Objects.equals(newValue, getItem())) {
// save data that this index has been edited
edited.put(getIndex(), Boolean.TRUE);
}
super.commitEdit(newValue);
}
});
请注意,如果 table 的项目列表被修改,您可能需要修改地图。
备选
使用存储项目是否被编辑的值类型而不是简单的 String
允许您保持代码简单,即使项目列表被修改:
public class EditableString {
private final boolean edited;
private final String value;
public EditableString(boolean edited, String value) {
this.edited = edited;
this.value = value;
}
public EditableString(String value) {
this(false, value);
}
public boolean isEdited() {
return edited;
}
public String getValue() {
return value;
}
}
StringConverter<EditableString> converter = new StringConverter<EditableString>() {
@Override
public String toString(EditableString object) {
return object == null ? null : object.getValue();
}
@Override
public EditableString fromString(String string) {
return string == null ? null : new EditableString(true, string);
}
};
TableColumn<LPAttributesTableObject, EditableString> column = (TableColumn) lpAttributesTable.getColumns().get(1);
column.setCellFactory(t -> new TextFieldTableCell<LPAttributesTableObject, EditableString>(converter) {
@Override
public void updateItem(EditableString item, boolean empty) {
super.updateItem(item, empty);
if (item != null && item.isEdited()) {
setStyle("-fx-font-weight: bold;");
} else {
setStyle("");
}
}
@Override
public void commitEdit(EditableString newValue) {
EditableString currentItem = getItem();
if (currentItem == null || newValue == null || !Objects.equals(newValue.getValue(), currentItem.getValue())) {
super.commitEdit(newValue);
} else {
// if the string is the same, keep the old value
super.commitEdit(currentItem);
}
}
});
请注意,这需要您将包含 String
的 LPAttributesTableObject
的 属性 更改为包含 EditableString
.[=19= 的 属性 ]
最后这就是我的意思。
StringConverter<EditableString> converter = new StringConverter<EditableString>() {
@Override
public String toString(EditableString object) {
System.out.println("bla bla");
return object == null ? null : object.toString();
}
@Override
public EditableString fromString(String string) {
System.out.println("bla");
return string == null ? null : new EditableString(true, string);
}
};
((TableColumn) lpAttributesTable.getColumns().get(1)).setCellValueFactory(new PropertyValueFactory<LPAttributesTableObject,EditableString>("val"));
((TableColumn) lpAttributesTable.getColumns().get(0)).setCellValueFactory(new PropertyValueFactory<LPAttributesTableObject,String>("attribute"));
TableColumn<LPAttributesTableObject, EditableString> col = (TableColumn) lpAttributesTable.getColumns().get(1);
col.setCellFactory(TextFieldTableCellEditable.<LPAttributesTableObject, EditableString>forTableColumn(converter));
我必须将现有的 TextFieldTableCell 对象扩展为:
public class TextFieldTableCellEditable<S,EditableString> extends TextFieldTableCell<S,EditableString> {
public static <S,EditableString> Callback<TableColumn<S,EditableString>, TableCell<S,EditableString>> forTableColumn(
final StringConverter<EditableString> converter) {
return list -> new TextFieldTableCellEditable<S, EditableString>(converter);
}
public TextFieldTableCellEditable(StringConverter<EditableString> converter) {
this.getStyleClass().add("text-field-table-cell");
setConverter(converter);
}
@Override
public final void updateItem(EditableString item, boolean empty) {
super.updateItem(item, empty);
if (item != null && ((sample.EditableString)item).isEdited()) {
setText(item.toString());
setStyle("-fx-font-weight: bold;");
} else if (item != null && !((sample.EditableString)item).isEdited()){
setStyle("");
setText(item.toString());
} else {
setStyle("");
setText(null);
}
}
@Override
public void commitEdit(EditableString newValue) {
EditableString currentItem = getItem();
if (currentItem == null || newValue == null || !Objects.equals(((sample.EditableString)newValue).getValue(), ((sample.EditableString)currentItem).getValue())) {
super.commitEdit(newValue);
} else {
// if the string is the same, keep the old value
super.commitEdit(currentItem);
}
}
}
LPAttributesTableObject 如下所示:
public class LPAttributesTableObject {
private String attribute;
private EditableString val;
public LPAttributesTableObject(String _attribute, EditableString _value)
{
this.attribute = _attribute;
this.val = _value;
}
public String getAttribute() { return attribute.toString(); }
public EditableString getVal() { return val; }
public final EditableString getValue() { return val; }
public StringProperty attributeProperty() { return new SimpleStringProperty(attribute.toString()); }
public ObjectProperty<EditableString> valProperty() { return new SimpleObjectProperty<EditableString>(this,"value",val); }
public void setAttribute(String _attr) { this.attribute = _attr;}
public void setValue(EditableString _value) { this.val = _value;}
public void setVal(EditableString _val) { this.val = _val; }
public void setVal(String _val) { this.val.setValue(_val);}
}
EditableString 看起来像这样:
public class EditableString {
private boolean edited;
private String string;
public EditableString(boolean edited, String val)
{
this.edited = edited;
this.string = val;
}
public EditableString(String val)
{
this.edited = false;
this.string = val;
}
public String getValue() { return string; }
public void setValue(String val) { this.string = val; }
public String toString() { return string; }
public boolean isEdited() { return edited; }
public void setValue(EditableString estr) { this.setValue(estr.getValue()); this.edited = estr.edited; }
}