Javafx Bug? Tableview无法正确呈现某些行

时间:2014-07-28 17:20:18

标签: java javafx javafx-8

实际上我在使用TableView的JavaFX应用程序中遇到了问题。我不是没有原因,但是,当我在运行时将数据加载到TableView时,JavaFX不会渲染某些行,如下图所示:

enter image description here

但是,当我调整列的大小时,会显示数据:

enter image description here

Bellow遵循使用的源代码:

public void loadData()
{   
    // Define the TableView columns using Reflection defined by ResultSetMetadata
    ArrayList<TableColumn> gridColumns = defineGridColumns(data.get(0));
    this.tableView.getColumns().clear();
    this.tableView.getColumns().addAll(gridColumns);

    // Load data to TableView
    this.tableView.setItems(FXCollections.observableArrayList(data));
}

private void defineGridColumns(Object singleData)
{
    ArrayList<TableColumn> gridColumns = new ArrayList<>();

    Field[] fields = singleData.getClass().getFields();
    for (int i = 0; i < fields.length; i++)
    {
        TableColumn column = createTableColumn(fields[i].getName());
        this.gridColumns.add(column);
    }

    return gridColumns;
}

private TableColumn createTableColumn(String columnName)
{
    TableColumn column = new TableColumn(columnName);
    column.setCellValueFactory(new PropertyValueFactory(columnName));
    column.setPrefWidth(columnName.length() * 20);

    HBox box = new HBox();
    box.setAlignment(Pos.CENTER);
    box.prefWidthProperty().bind(column.widthProperty().subtract(5));
    box.setSpacing(10.0);
    box.getChildren().addAll(new Label(column.getText()));
    column.setGraphic(box);

    // Align the cell content in center
    column.setCellFactory(new Callback<TableColumn, TableCell>()
    {
        @Override
        public TableCell call(TableColumn param)
        {
            TableCell cell = new TableCell()
            {
                @Override
                public void updateItem(Object item, boolean empty)
                {
                    if (item != null)
                    {
                        setText(item.toString());
                    }
                }
            };
            cell.setAlignment(Pos.CENTER);
            return cell;
        }
    });

    return column;
}   

嗯,我做错了什么?我已经将Java更新为最新版本(JDK 1.8.11)。

感谢大家!


姑息解决方案

当调整列宽大小会触发JavaFX显示数据时,我做了一个方法,在加载数据后更改所有列大小:

public void loadData()
{   
    // Define the TableView columns using Reflection defined by ResultSetMetadata
    ArrayList<TableColumn> gridColumns = defineGridColumns(data.get(0));
    this.tableView.getColumns().clear();
    this.tableView.getColumns().addAll(gridColumns);

    // Load data to TableView
    this.tableView.setItems(FXCollections.observableArrayList(data));

    // HACK to force JavaFX display all data
    final TrendAnalysisTabController thisController = this;
    Platform.runLater(new Runnable()
    {
        @Override
        public void run()
        {
            thisController.adjustAllColumnWidths();
        }
    });
}

private void adjustAllColumnWidths()
{
    TableViewSkin<?> skin = (TableViewSkin<?>) this.tableView.getSkin();
    TableHeaderRow headerRow = skin.getTableHeaderRow();
    NestedTableColumnHeader rootHeader = headerRow.getRootHeader();
    for (TableColumnHeader columnHeader : rootHeader.getColumnHeaders())
    {
        try
        {
            TableColumn<?, ?> column = (TableColumn<?, ?>) columnHeader.getTableColumn();
            if (column != null)
            {
                // Changes the width column and rollback it
                double prefWidth = column.getPrefWidth();
                column.setPrefWidth(prefWidth + 0.01);
                column.setPrefWidth(prefWidth);
            }
        }
        catch (Throwable e)
        {
            log.log(Level.SEVERE, "Error adjusting columns widths: " + e.getMessage(), e);
        }
    }
}

2 个答案:

答案 0 :(得分:5)

因为TableCells被重用,你需要明确地&#34;清除&#34;它们在你的updateItem方法中:

@Override
public void updateItem(Object item, boolean empty)   {
   super.updateItem(item, empty);
   if (item == null || empty)   {
       setText(null);
   } else{
        setText(item.toString());
   }
}

答案 1 :(得分:1)

我不确定这是否可以解决您的问题,但在创建TableCell实施时,您的updateItem(...)方法必须致电super.updateItem(...)

 column.setCellFactory(new Callback<TableColumn, TableCell>()
    {
        @Override
        public TableCell call(TableColumn param)
        {
            TableCell cell = new TableCell()
            {
                @Override
                public void updateItem(Object item, boolean empty)
                {
                    // Don't omit this:
                    super.updateItem(item, empty);
                    if (item != null)
                    {
                        setText(item.toString());
                    }
                }
            };
            cell.setAlignment(Pos.CENTER);
            return cell;
        }
    });