以编程方式编辑TreeView / TreeItem

时间:2015-04-25 08:53:21

标签: java treeview javafx-8

编辑#2 :由于它看起来像一个错误,我已在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);
    }
}

我使用的CellFactory是part of the JavaFX api

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

我通过google找到的许多示例this为每个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);
        }
    });
}

每个新项目都已正确标记为编辑(已创建的文本字段及其内容已选中)。 没有 Thread.sleep Platform.runLater无效,而 Thread.sleep 没有 runLater

这感觉不对。我的问题是什么?

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

2 个答案:

答案 0 :(得分:6)

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

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

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

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

答案 1 :(得分: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);
}

这种解决方法完全基于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();