显示TableView <observablelist <string>&gt;在TreeView <e>中

时间:2015-06-01 08:09:50

标签: java javafx treeview treetableview

我想到的设计是这样的: 有一个TreeView<E>,其中E是一个包装类,其实现可能如下所示:

public class E {
    private int key;
    private String value;

    public E(int key, String value) {
        this.key = key;
        this.value = value;
    }

    public int getKey(){
        return key; 
    }

    public String getValue() {
        return value;
    }

    public String toString(){
        return value;
    }
}

因此TreeView<E>将包含一堆TreeItem<E>个实例。 toString() E方法显示值。

当您按下任何树项目时,我希望TableView<ObservableList<String>>显示在所选TreeItem<E>下方,其中包含连接到{{1的键值>的数据库中的所有行}}

这可能吗?我知道TreeItem<E>是一个不错的选择,但我不想显示任何列,除非我按下其中一个树项。我希望每个TreeTableView都有自己的表。虽然,对于记录,所有表都将具有相同的列,只有不同的行数。

更新: 在@Uluk Biy的帮助下,我设法实现了一个解决方案,但它包含一个错误。

问题在于,当我在TreeView中按下TreeItem时,被选中的节点是第一个节点下面两个步骤的节点,当我按下TreeItem时,滚动窗格中不可见(TreeView自动包含滚动窗格)。因此,如果我拉伸窗口以便隐藏少于3个树项目,则不会显示任何内容。并不是TableView被显示在错误的位置,问题是没有选择正确的树项(我知道这是因为我打印出了键值。

这是一个显示此错误的SSCCE。在表格中选择包装器1,将选择包装器6。如果更改TreeView的大小以便隐藏少于三个TreeItem,则无法选择任何内容。

TreeItem<E>

1 个答案:

答案 0 :(得分:1)

设置自定义单元工厂不是一种方法。因为单元格被重复用于渲染多个项目,所以如果最初所有单元格在树视图的视口中都可见,则只需对项目进行默认选择就不会触发单元格的重用,因此不会对updateItem()进行调用。另一方面,如果视口之外还有其他项目并且用户向下滚动到它们,那么将重新使用上部不可见项目的单元格来渲染新输入到视口的项目。这个imo是对下面评论中描述的行为的解释。简而言之,定义自定义TreeCell不是正确的方法,而是我们可以观察项目选择更改并在其中设置图形:

treeView.getSelectionModel().selectedItemProperty().addListener( ( ObservableValue<? extends TreeItem<Wrapper>> observable,
        TreeItem<Wrapper> oldValue, TreeItem<Wrapper> newValue ) ->
        {
            System.out.println( "Selected newValue: " + newValue );

            if ( oldValue != null )
            {
                // hide graphic of previous selected item
                oldValue.setGraphic( null );
            }

            if ( newValue != null )
            {
                TableView<ObservableList<String>> table = new TableView<>();
                for ( int i = 0; i < columns.size(); i++ )
                {
                    final int j = i;

                    TableColumn<ObservableList<String>, String> column = new TableColumn<>(
                            columns.get( i ) );

                    column.setCellValueFactory( (
                                    TableColumn.CellDataFeatures<ObservableList<String>, String> param ) -> 
                            new SimpleStringProperty( param.getValue().get( j ) ) );

                    table.getColumns().add( column );
                }

                ObservableList<ObservableList<String>> selected_data = FXCollections
                .observableArrayList();

                for ( int i = 0; i < data.size(); i++ )
                {
                    if ( Integer.parseInt( data.get( i ).get( 0 ) ) == newValue.getValue().getKey() )
                    {
                        selected_data.add( data.get( i ) );
                    }
                }
                table.setItems( selected_data );
                VBox vbox = new VBox( new Label( newValue.getValue().getValue() ), table );
                newValue.setGraphic( vbox );
            }
        } );

设置treeView.setCellFactory(...)。现在的问题是如何隐藏项目的文本。