简体   繁体   English

可编辑的TableTreeView,如何取消编辑

[英]Editable TableTreeView, how to cancel edit

I have made an editable TreeTableView. 我做了一个可编辑的TreeTableView。 I want to offer editable feature based on row contents. 我想提供基于行内容的可编辑功能。

final TreeTableColumn<XXX, String> col = new TreeTableColumn<>( "Title" );
col.setCellValueFactory( new TreeItemPropertyValueFactory<XXX, String >( "name"));
col.setCellFactory( TextFieldTreeTableCell.forTreeTableColumn());
col.setOnEditStart( e -> {
   final XXX x = e.getRowValue().getValue();
   if( ! x.isEditable()) {
      throw new IllegalStateException();
   }
   e.consume();
});

This solution works well but I prefer to call Cell.cancelEdit() but I don't find how without overriding a lot of classes. 该解决方案效果很好,但是我更喜欢调用Cell.cancelEdit(),但是我发现不重写很多类就不会怎么做。

I hope a simple instruction (or two) do the trick. 我希望一个简单的指令(或两个)可以解决问题。

Cells already have an editable property , so you can just call setEditable(...) on the cell as needed: 单元格已经具有editable属性 ,因此您可以根据需要在单元格上调用setEditable(...)

Callback<TreeTableColumn<XXX, String>, TreeTableCell<XXX, String>> defaultCellFactory = TextFieldTreeTableCell.forTreeTableColumn() ;
col.setCellFactory(c -> {
    TreeTableCell<XXX, String> cell = defaultCellFactory.call(c);
    cell.indexProperty().addListener((obs, oldIndex, newIndex) -> {
        if (newIndex.intValue() >= 0 ) {
            TreeItem<XXX> item = cell.getTreeTable().getTreeItems(newIndex.intValue());
            boolean canEdit = /* logic depending on item */
            cell.setEditable(canEdit);
        } else {
            cell.setEditable(false);
        }
    });
    return cell ;
});

Your logic may vary depending on exactly what you want to do, eg you might use bindings instead of the listener on the indexProperty , or a listener on the itemProperty() , or possibly something more sophisticated, but this general structure should work. 您的逻辑可能会根据您要执行的操作而有所不同,例如,您可以使用绑定而不是indexProperty上的侦听器或itemProperty()上的侦听器,或者可能使用更复杂的方法,但是这种常规结构应该可以工作。

Here's a complete example. 这是一个完整的例子。 TreeItem s containing Employee s have an editable name column, TreeItem s containing Department s don't: 包含EmployeeTreeItem具有可编辑的name列,而包含DepartmentTreeItem没有:

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
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.TextFieldTreeTableCell;
import javafx.scene.control.cell.TreeItemPropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Callback;

public class TreeTableCustomEditable extends Application {

    @Override
    public void start(Stage primaryStage) {


        TreeItem<Object> root = new TreeItem<>();
        TreeItem<Object> it = new TreeItem<>(new Department("IT"));
        TreeItem<Object> management = new TreeItem<>(new Department("Management"));
        TreeItem<Object> bill = new TreeItem<>(new Employee("1", "Bill Gates"));
        TreeItem<Object> tim = new TreeItem<>(new Employee("2", "Tim Cook"));
        TreeItem<Object> larry = new TreeItem<>(new Employee("3", "Larry Ellison"));
        TreeItem<Object> larryP = new TreeItem<>(new Employee("4", "Larry Page"));

        it.getChildren().addAll(larry, larryP);
        management.getChildren().addAll(bill, tim);
        root.getChildren().addAll(it, management);

        TreeTableView<Object> treeTableView = new TreeTableView<>();
        treeTableView.setEditable(true);
        treeTableView.setRoot(root);
        treeTableView.setShowRoot(false);

        TreeTableColumn<Object, String> idCol = new TreeTableColumn<>("ID");
        idCol.setCellValueFactory(new TreeItemPropertyValueFactory<Object, String>("id"));
        TreeTableColumn<Object, String> nameCol = new TreeTableColumn<>("Name");
        nameCol.setCellValueFactory(new TreeItemPropertyValueFactory<Object, String>("name"));

        Callback<TreeTableColumn<Object, String>, TreeTableCell<Object, String>> defaultCellFactory = TextFieldTreeTableCell.forTreeTableColumn() ;
        nameCol.setCellFactory(c -> {
            TreeTableCell<Object, String> cell = defaultCellFactory.call(c);
            cell.indexProperty().addListener((obs, oldIndex, newIndex) -> {
                if (newIndex.intValue() >= 0) {
                    TreeItem<Object> item = cell.getTreeTableView().getTreeItem(newIndex.intValue());
                    boolean canEdit = item != null && item.getValue() instanceof Employee ;
                    cell.setEditable(canEdit);
                } else {
                    cell.setEditable(false);
                }
            });
            return cell ;
        });

        treeTableView.getColumns().addAll(idCol, nameCol);
        BorderPane uiRoot = new BorderPane(treeTableView);
        primaryStage.setScene(new Scene(uiRoot, 600, 600));
        primaryStage.show();
    }

    public static class Employee {
        private final StringProperty id = new SimpleStringProperty();
        private final StringProperty name = new SimpleStringProperty();

        public Employee(String id, String name) {
            setId(id);
            setName(name);
        }

        public final StringProperty idProperty() {
            return this.id;
        }

        public final java.lang.String getId() {
            return this.idProperty().get();
        }

        public final void setId(final java.lang.String id) {
            this.idProperty().set(id);
        }

        public final StringProperty nameProperty() {
            return this.name;
        }

        public final java.lang.String getName() {
            return this.nameProperty().get();
        }

        public final void setName(final java.lang.String name) {
            this.nameProperty().set(name);
        }


    }

    public static class Department {
        private final StringProperty id = new SimpleStringProperty();

        public Department(String id) {
            setId(id);
        }

        public final StringProperty idProperty() {
            return this.id;
        }

        public final java.lang.String getId() {
            return this.idProperty().get();
        }

        public final void setId(final java.lang.String id) {
            this.idProperty().set(id);
        }


    }

    public static void main(String[] args) {
        launch(args);
    }
}

I have found a solution but not in one instruction nor two... :-( 我找到了一种解决方案,但没有一条指令,也没有两条... :-(

Explicit feature: 显式功能:

public interface IEditable {

   public boolean isEditable();
}

Using feature in a TextFieldTreeTableCell : TextFieldTreeTableCell使用功能:

final class EditableTextFieldTreeTableCell<S extends IEditable>
   extends TextFieldTreeTableCell<S, String>
{
   public static <S extends IEditable>
   Callback<TreeTableColumn<S,String>, TreeTableCell<S,String>> getCallback() {
      return list -> new EditableTextFieldTreeTableCell<>( new DefaultStringConverter());
   }

   public EditableTextFieldTreeTableCell( StringConverter<String> converter ) {
      super( converter );
   }

   @Override
   public void startEdit() {
      setEditable( getTreeTableRow().getItem().isEditable());
      super.startEdit();
   }
}

Using the new specialized Cell class in the main: 在主体中使用新的专用Cell类:

final TreeTableColumn<XXX, String> col = new TreeTableColumn<>( "Title" );
col.setCellValueFactory( new TreeItemPropertyValueFactory<XXX, String >( "name"));
col.setCellFactory( EditableTextFieldTreeTableCell.getCallback());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM