Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
683 views
in Technique[技术] by (71.8m points)

java - Programmatically edit TreeView/TreeItem

Edit #2: Since it looks like a bug i already posted a bug report in the javaFx-jira. You have to have an account to have access to the issue. I will keep this post up-to-date, if there is new information.

Original post: I have a simple UI with a button and a TreeView. If the button gets pressed there should be a new item added to the TreeView. This item should be editable as soon as it appears in the tree.

import javafx.fxml.FXML;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.util.converter.DefaultStringConverter;

public class ClientController {

    @FXML
    private TreeView<String> tree;

    public void initialize() {
        tree.setEditable(true);
        tree.setCellFactory(p -> new TextFieldTreeCell<>(new DefaultStringConverter()));

        TreeItem<String> root = new TreeItem<>();
        root.setValue("Items");
        root.setExpanded(true);

        tree.setRoot(root);
    }

    @FXML
    public void createItem() {
        TreeItem<String> newItem = new TreeItem<>();
        newItem.setValue("Item " + tree.getExpandedItemCount());

        tree.getRoot().getChildren().add(newItem);
        tree.requestFocus();
        tree.getSelectionModel().select(newItem);
        tree.edit(newItem);
    }
}

The CellFactory i am using is part of the JavaFX api.

If I have a look at the api-documentation (TreeView#edit) there is not much to do on my site.

Many examples I found via google like this create a context-menu for each TreeItem. Useful, but not exactly what i want, right now.

If I select/double-click the item in the UI I am able to edit any previously created and existing TreeItem. Do I miss something?

Edit #1:

If the createItem method gets changed to the following code:

@FXML
public void createItem() throws InterruptedException {
    TreeItem<String> newItem = new TreeItem<>();
    newItem.setValue("Item " + this.tree.getExpandedItemCount());

    this.tree.getRoot().getChildren().add(newItem);
    this.tree.requestFocus();
    this.tree.getSelectionModel().select(newItem);
    Thread.sleep(100);
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            SimpleController.this.tree.edit(newItem);
        }
    });
}

every new item is correctly marked for edit (the created textfield and its content are selected). Using Platform.runLater without Thread.sleep doesnt work and Thread.sleep without runLater neither.

This simply does not feel right. What is my problem?

I provide a very small example (eclipse) project: https://www.dropbox.com/s/duos0ynw4rqp3yn/Test.zip?dl=0 containing The main-method, the FXML-File and the "problematic" controller.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

TreeCells (that is their content and binding to the treeItem) are updated lazily in a layout pass, that is very "late" when the next pulse is fired. A Platform.runLater(..) or any hard-coded delay may happen before or after that pulse, that's (probably) why both seem to work or not spuriously.

So another whacky hack is to manually force a re-layout on the tree after having added a new item and before programatically starting an edit:

root.getChildren().add(newItem);
tree.layout();
tree.edit(newItem);

Needless to say, that this shouldn't be necessary - the current behaviour is a severe bug and must be fixed at once (... meaning ... jdk 9)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...