如何禁用treetableview中父行中可编辑的任何单元格?请查看图片并查看示例代码。不久我想在行可扩展(根行或子根行)
时禁用行可编辑**示例代码**
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringWrapper;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TreeTableExample extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
@SuppressWarnings("unchecked")
public void start(Stage stage) {
HBox root = new HBox(createTable());
Scene scene = new Scene(root);
stage.setScene(scene);
stage.setTitle("Using a TreeTableView");
stage.show();
}
public TreeTableView createTable() {
TreeTableView<Person> treeTable = new TreeTableView<>();
treeTable.setEditable(true);
Callback<TreeTableColumn<Person, String>,
TreeTableCell<Person, String>> cellFactory
= (TreeTableColumn<Person, String> p) -> new EditingCell();
TreeTableColumn<Person, String> firstName = new TreeTableColumn<>("First Name");
firstName.setCellValueFactory(new TreeItemPropertyValueFactory<>("firstName"));
firstName.setCellFactory(cellFactory);
firstName.setOnEditCommit((TreeTableColumn.CellEditEvent<Person, String> event) -> {
if(event.getNewValue()!=null)
event.getRowValue().getValue().setFirstName(event.getNewValue());
});
TreeTableColumn<Person, String> lastName = new TreeTableColumn<>("Last Name");
lastName.setCellValueFactory(new TreeItemPropertyValueFactory<>("lastName"));
lastName.setCellFactory(cellFactory);
lastName.setOnEditCommit((TreeTableColumn.CellEditEvent<Person, String> event) -> {
if(event.getNewValue()!=null)
event.getRowValue().getValue().setLastName(event.getNewValue());
});
treeTable.getColumns().addAll(firstName, lastName);
TreeItem<Person> root = new TreeItem<>();
for (int i = 0; i < 5; i++) {
root.getChildren().add(new TreeItem<>(new Person()));
}
treeTable.setRoot(root);
return treeTable;
}
public class Person {
private SimpleStringProperty firstName;
private SimpleStringProperty lastName;
public Person(){
firstName = new SimpleStringProperty(this, "firstName");
lastName = new SimpleStringProperty(this, "lastName");
};
public String getFirstName() {
return firstName.get();
}
public void setFirstName(String fName) {
firstName.set(fName);
}
public String getLastName() {
return lastName.get();
}
public void setLastName(String fName) {
lastName.set(fName);
}
}
class EditingCell extends TreeTableCell<Person, String> {
private TextField textField;
public EditingCell() {
}
@Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else if (isEditing()) {
if(!getTreeTableView().getTreeItem(getIndex()).isLeaf())
setEditable(false);
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.focusedProperty().addListener(
(ObservableValue<? extends Boolean> arg0,
Boolean arg1, Boolean arg2) -> {
if (!arg2) {
commitEdit(textField.getText());
}
});
}
private String getString() {
return getItem() == null ? "" : getItem();
}
}
}
运行它并双击根项目
make-individual-cell-editable-in-javafx-tableview我检查了解决方案适用于tableview,但treetaleview不起作用。
答案 0 :(得分:2)
在决定是否致电TreeTableCell
之前,似乎editable
未正确检查其startEdit()
属性。我认为这是一个错误。您可以通过startEdit()
方法检查自己来解决此问题:
@Override
public void startEdit() {
if (isEditable() && !isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
现在在您的updateItem()
方法中,您可以检查该行中的当前树项,并根据需要更新editable
:
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
TreeItem<Person> treeItem = getTreeTableRow().getTreeItem();
setEditable(treeItem != null && treeItem.isLeaf());
if (empty) {
setText(null);
setGraphic(null);
} else if (isEditing()) {
if(!getTreeTableView().getTreeItem(getIndex()).isLeaf())
setEditable(false);
if (textField != null) {
textField.setText(getString());
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
答案 1 :(得分:0)
实际上我不同意other answer中的推理:核心TreeTableCell没有任何问题( 在实际开始编辑之前检查其可编辑性) - 而不是自定义单元格实现已破坏。特别是,updateItem用于设置可编辑属性的部分:
} else if (isEditing()) {
if(!getTreeTableView().getTreeItem(getIndex()).isLeaf())
setEditable(false);
除了在不将任何地方的可编辑状态重置为真时不完整(记住:重复使用单元格),我们允许超级首先开始编辑,只有在之后开始了,它被禁用了。
通过在updateItem中无条件地设置可编辑性,修复了此逻辑错误(在另一个答案中,为方便起见,此处复制):
super.updateItem(item, empty);
TreeItem<Person> treeItem = getTreeTableRow().getTreeItem();
setEditable(treeItem != null && treeItem.isLeaf());
在实际配置编辑器之前,其他使用错误(如前所述)未完全检查单元状态。建议的修复 - 检查单元格的可编辑 - 并不完全,因为表/列可编辑性也可能被禁用。考虑到这一点,我倾向于让super执行其工作,只有在可编辑性实际发生变化时才配置编辑器,例如
super.startEdit();
// super changed state into editing
if (isEditing()) {
// create and install the textField
}