以编程方式编辑TreeView/TreeItem

sem*_*Tex 3 java treeview javafx-8

编辑#2:因为它看起来像一个bug我已经在javaFx-jira中发布了一个错误报告.您必须拥有一个帐户才能访问该问题.如果有新信息,我会保持这篇文章是最新的.

原帖: 我有一个带按钮和TreeView的简单UI.如果按下按钮,则应该在TreeView中添加一个新项目.该项目一出现在树中就应该可以编辑.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用的CellFactory是JavaFX api的一部分.

如果我查看api文档(TreeView#edit),我的网站上没什么可做的.

我通过谷歌找到类似的例子很多这样为每个TreeItem上下文菜单.有用,但不完全是我想要的,现在.

如果我选择/双击UI中的项目,我可以编辑任何以前创建的和现有的TreeItem.我错过了什么吗?

编辑#1:

如果createItem方法更改为以下代码:

@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);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

每个新项目都已正确标记为编辑(已选择创建的文本字段及其内容).使用不带Thread.sleep的Platform.runLater不起作用,Thread.sleep也没有runLater.

这根本感觉不对.我的问题是什么?

我提供了一个非常小的示例(eclipse)项目:https: //www.dropbox.com/s/duos0ynw4rqp3yn/Test.zip?dl = 0包含主方法,FXML文件和"有问题"的控制器.

kle*_*tra 6

TreeCells(这是它们的内容和对treeItem的绑定)在布局传递中被懒惰地更新,当下一个脉冲被触发时非常"迟".Platform.runLater(..)或任何硬编码延迟可能发生在该脉冲之前或之后,这(可能)为什么两者似乎都是虚假的.

所以另一个糟糕的黑客是在添加新项目之后以及以编程方式开始编辑之前手动强制在树上重新布局:

root.getChildren().add(newItem);
tree.layout();
tree.edit(newItem);
Run Code Online (Sandbox Code Playgroud)

毋庸置疑,这不应该是必要的 - 当前行为是一个严重的错误,必须立即修复(...意思是...... jdk 9)


Ulu*_*Biy 5

看来,在新添加的项目被反射到它之前,treeView需要更多时间来进行内部计算.要确切地确定导致问题的计算,需要挖掘源代码并查看引擎盖下的内容.

解决方法是强制treeView立即执行计算,

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

    tree.getRoot().getChildren().add(newItem);

    // Trigger whatever calculations there internally
    TreeItem<String> r = tree.getRoot();
    tree.setRoot( null );
    tree.setRoot( r );

    tree.requestFocus();
    tree.getSelectionModel().select(newItem);
    tree.edit(newItem);
}
Run Code Online (Sandbox Code Playgroud)

这个解决方法完全基于JavaFX中的其他错误直观地发现;-)


或者,由于Platform.runlaters推迟的时间显然不够,您可以使用PauseTransition增加所需的时间:

PauseTransition p = new PauseTransition( Duration.millis( 100 ) );
p.setOnFinished( new EventHandler<ActionEvent>()
{
    @Override
    public void handle( ActionEvent event )
    {
        tree.edit( newItem );
    }
} );
p.play();
Run Code Online (Sandbox Code Playgroud)