Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8096896

TreeTableView editing cell via edit(index, column) results in wrong cell entering editmode

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • P3
    • 8u40
    • 8u20
    • javafx
    • Windows 7, JDK (1.8.0_20-ea-b19)

    Description

      I created a ButtonClick-Action, to create a new Child-Node for a selected TreeItem, expand the selected TreeItem and enter editing-mode for the newly created Child. Unfortunatly a wrong cell is entering editing-mode, even though the editingCellProperty is set correctly. When the editing-mode is finished, the correct TreeItem gets changed.

      My intended workflow was the following: User initiates an action which results in a new TreeItem in a TreeTableView below the currently selected TreeItem. The selected Parent should get expanded and the newly created Item should enter editing-mode, so the user can directly enter the desired name.

      In the latest official JDK Version (8u5), I did not succed entering editing-mode most of the time, which is why I created a Stackoverflow post (http://stackoverflow.com/questions/24290072/why-javafx-treetableview-edit-mode-gets-undesirably-canceled), but there I have been told, that with Version 8u20-ea my posted example would work.

      After changing to the newest JDK (1.8.0_20-ea-b19) version it indeed entered editmode and everything seemed ok, until I changed the size of the window, then suddenly the TreeTableView mixed up indeces and the described behaviour occured.

      The bug occurs in most stage-sizes, for example 400x800, but when I set it to 400x400 it suddenly works as expected. So I am wondering if there is any relationship between the cell-index and the stage-size? Is there anything I am doing wrong? I was not able to find any explanation for this sort of behaviour.

      Here the Example, where the described behaviour occurs.

      /**
       * Small Example to evaluate, why the wrong cell gets targeted when initializing edit mode by index.
       *
       * Intended Workflow: User clicks a Button to create a new Child-Node for a selected TreeItem, expand the
       * selected TreeItem and enter editing-mode for the newly created Child. Unfortunatly a wrong cell is entering
       * editing-mode, even though the editingCellProperty is set correctly. When the editing-mode is finished, the
       * correct TreeItem gets changed.
       *
       * @author ymene
       */
      import javafx.application.Application;
      import javafx.beans.property.IntegerProperty;
      import javafx.beans.property.SimpleIntegerProperty;
      import javafx.beans.property.SimpleStringProperty;
      import javafx.beans.property.StringProperty;
      import javafx.beans.value.ChangeListener;
      import javafx.beans.value.ObservableValue;
      import javafx.event.ActionEvent;
      import javafx.event.EventHandler;
      import javafx.scene.Scene;
      import javafx.scene.control.Button;
      import javafx.scene.control.TreeItem;
      import javafx.scene.control.TreeTableColumn;
      import javafx.scene.control.TreeTablePosition;
      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;

      public class TreeTableViewCreateExpandAndEditMain extends Application {
          private int id = 0;

          @Override
          public void start(final Stage primaryStage) {
              //Generating Testdata:
              TreeItem<Item> root = new TreeItem<>(new Item(++id, "Root"));

              TreeItem<Item> item1 = new TreeItem<>(new Item(++id, "Item1"));
              TreeItem<Item> item11 = new TreeItem<>(new Item(++id, "Item11"));
              TreeItem<Item> item2 = new TreeItem<>(new Item(++id, "Item2"));
              TreeItem<Item> item3 = new TreeItem<>(new Item(++id, "Item3"));
              TreeItem<Item> item31 = new TreeItem<>(new Item(++id, "Item31"));

              root.getChildren().add(item1);
              item1.getChildren().add(item11);
              root.getChildren().add(item2);
              root.getChildren().add(item3);
              item3.getChildren().add(item31);

              TreeTableColumn<Item, Integer> columnId = new TreeTableColumn<>("ColumnId");
              TreeTableColumn<Item, String> columnName = new TreeTableColumn<>("ColumnName");

              columnId.setCellValueFactory(new TreeItemPropertyValueFactory<Item, Integer>("id"));
              columnName.setCellValueFactory(new TreeItemPropertyValueFactory<Item, String>("name"));

              //Using Default-CellFactory:
              columnName.setCellFactory(TextFieldTreeTableCell.forTreeTableColumn());

              //Commiting Cellcontent-Changes:
              columnName.setOnEditCommit(new EventHandler<TreeTableColumn.CellEditEvent<Item, String>>() {
                  @Override
                  public void handle(final TreeTableColumn.CellEditEvent<Item, String> event) {
                      final Item item = event.getRowValue().getValue();
                      System.out.println("Change Item " + item + " from " + event.getOldValue() + " to new value "
                              + event.getNewValue());
                      item.setName(event.getNewValue());
                  }
              });

              //Creating TreeTableView:
              final TreeTableView<Item> treeTableView = new TreeTableView<>(root);

              //Listener at editingCellProperty, to keep track, what is happening here:
              treeTableView.editingCellProperty().addListener(new ChangeListener<TreeTablePosition<Item, ?>>() {
                  @Override
                  public void changed(final ObservableValue<? extends TreeTablePosition<Item, ?>> observable,
                                      final TreeTablePosition<Item, ?> oldValue,
                                      final TreeTablePosition<Item, ?> newValue) {
                      System.out.println("EditingCellProperty changed to: "
                              + (newValue != null ? newValue.getTreeItem() : newValue)
                              + (newValue != null ? " at row " + newValue.getRow() : ""));
                  }
              });

              treeTableView.getColumns().add(columnName);
              treeTableView.getColumns().add(columnId);
              treeTableView.setShowRoot(false);
              treeTableView.setColumnResizePolicy(TreeTableView.CONSTRAINED_RESIZE_POLICY);

              treeTableView.setEditable(true);
              columnId.setEditable(false);

              BorderPane layout = new BorderPane();

              Button button = new Button("DoAction!");
              button.setOnAction(new EventHandler<ActionEvent>() {
                  @Override
                  public void handle(final ActionEvent event) {
                      createNodeAtSelectedAsChild();
                  }

                  private void createNodeAtSelectedAsChild() {
              /*
               * This Method should create a new node at the currently selected node, expand the selected node and start editing the new created node, after selecting it.
               */
                      final TreeItem<Item> selectedItem = treeTableView.getSelectionModel().getSelectedItem();

                      final TreeItem<Item> newItem =
                              new TreeItem<>(new Item(++id, "newItemFor" + selectedItem.getValue().getName()));
                      selectedItem.getChildren().add(newItem);

                      selectedItem.expandedProperty().set(true);
                      final int rowIndex = treeTableView.getRow(newItem);

                      // treeTableView.getSelectionModel().select( rowIndex );//The desired row gets selected
                      //
                      // System.out.println( "Edit Row: " + rowIndex + " edit Value: " + newItem.getValue().getName() );
                      // System.out.println( "SelectedIndex: " + treeTableView.getSelectionModel().getSelectedIndex() );

                      treeTableView.edit(rowIndex, columnName);//Wrong Cell edited, why? Especially this seems to depend on Stage-Size. At 400x400 it works.
                  }
              });

              layout.setCenter(treeTableView);
              layout.setBottom(button);

              Scene scene = new Scene(layout, 400, 800);
              primaryStage.setScene(scene);
              primaryStage.show();
          }

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


          public static class Item {
              private final IntegerProperty id = new SimpleIntegerProperty();
              private final StringProperty name = new SimpleStringProperty();

              public Item(final int id, final String name) {
                  this.id.set(id);
                  this.name.set(name);
              }

              public int getId() {
                  return id.get();
              }

              public String getName() {
                  return name.get();
              }

              public void setId(final int id) {
                  this.id.set(id);
              }

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

              public IntegerProperty idProperty() {
                  return id;
              }

              public StringProperty nameProperty() {
                  return name;
              }

              @Override
              public String toString() {
                  return "[Item: " + "name=" + getName() + ", id=" + getId() + "]";
              }
          }
      }

      Attachments

        Activity

          People

            jgiles Jonathan Giles
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported: