10

Problem

I want to add data dynamically to a TableView and scroll to the new data's position. But when the rows in the TableView reach the ViewPort size, I get this in the console:

Apr 18, 2015 9:14:34 AM com.sun.javafx.scene.control.skin.VirtualFlow addTrailingCells INFO: index exceeds maxCellCount. Check size calculations for class javafx.scene.control.TableRow

So I guess I did something wrong. All I did was using the Oracle TableView example and add this:

// button to add new data
Button bt = new Button( "Add");
bt.setOnAction(e -> {

    // insert new item
    int i = data.size() + 1;
    Person person = new Person( "Name " + i, "Name " + i, "Mail " + i);
    data.add( person);

    // scroll to new item
    table.scrollTo( person);

});

The same happens when you use

    table.getItems().add( person);

instead of modifying the list.

The culprit is the scrollTo method. The same info/error occurs when you use the row index with the scrollTo method.

Question

How do you add new items correctly to a TableView, so that the info/error doesn't show up?

Code

Here's a full example. The table is pre-filled. If you hit the Add button the viewport size is reached and the info (or error?) is displayed in the console.

public class TableViewSample extends Application {

    private TableView<Person> table = new TableView<Person>();
    private final ObservableList<Person> data = FXCollections.observableArrayList();

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(450);
        stage.setHeight(500);

        table.setEditable(true);

        TableColumn firstNameCol = new TableColumn("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("firstName"));

        TableColumn lastNameCol = new TableColumn("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("lastName"));

        TableColumn emailCol = new TableColumn("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(
                new PropertyValueFactory<Person, String>("email"));

        table.setItems(data);
        table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);

        // -------------------------------
        // dynamically add data
        // -------------------------------

        // fill table with data
        for( int i=0; i < 14; i++) {
            Person person = new Person( "Name " + i, "Name " + i, "Mail " + i);
            data.add( person);
        }

        // button to add new data
        Button bt = new Button( "Add");
        bt.setOnAction(e -> {

            // insert new item
            int i = data.size() + 1;
            Person person = new Person( "Name " + i, "Name " + i, "Mail " + i);
            data.add( person);

            // scroll to new item
            table.scrollTo( person);

        });

        // -------------------------------

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.getChildren().addAll(table, bt);

        ((Group) scene.getRoot()).getChildren().addAll(vbox);

        stage.setScene(scene);
        stage.show();


    }

    public static class Person {

        private final SimpleStringProperty firstName;
        private final SimpleStringProperty lastName;
        private final SimpleStringProperty email;

        private Person(String fName, String lName, String email) {
            this.firstName = new SimpleStringProperty(fName);
            this.lastName = new SimpleStringProperty(lName);
            this.email = new SimpleStringProperty(email);
        }

        public String getFirstName() {
            return firstName.get();
        }

        public void setFirstName(String fName) {
            firstName.set(fName);
        }

        public String getLastName() {
            return lastName.get();
        }

        public void setLastName(String fName) {
            lastName.set(fName);
        }

        public String getEmail() {
            return email.get();
        }

        public void setEmail(String fName) {
            email.set(fName);
        }
    }
} 
4
  • Do you want to scroll always to the bottom of the TableView? Commented Apr 18, 2015 at 7:24
  • No, there may be use cases in which the new row isn't at the bottom. Example: Focus is on row 5, user scrolls down to row 100. Row 5 isn't visible. User presses "insert" button. Row should be added at position 6 and the table should be scrolled to that new row. Commented Apr 18, 2015 at 7:34
  • Seems like a bug to me, as this only happens as long as the TableView contains no ScrollBars. Commented Apr 18, 2015 at 8:31
  • @Roland, seems like this issue persists in new Java versions (8_51) and the Jira Bug Tracker is about to be removed from that site. I'll recommend you to update that issue request to somewhere else. Commented Aug 11, 2015 at 16:14

3 Answers 3

4

I solved this problem using fixed cells..

listCategory.setFixedCellSize(40); 

or

-fx-fixed-cell-size : 40;
Sign up to request clarification or add additional context in comments.

I am facing the issue, that beside showing the unhelpful addTrailingCells logmessage, the listview loads sometimes really slow but mostly fine. Setting the fixed cell size helped for that issue too. With that it loads at constant speed without logmessage.
Hi yes, the virtual flow in list-view does calculations fixed.. it's don't calculate new values when you modify a size from inner cells.. then fixed cell size works.. if you need this.. try to use flowless this lib is very good.. regards.
This fixed my issue, no longer getting that error, thanks!
0

I dont find a solution but the problem is not about using scrollTo() method it's always happen when you're scroll to bottom (even manually) and increase the window height when the scroll disappear i don't know why need to open a bug ticket

This will scroll to the bottom of the list. The original problem was to scroll to a specific row.
0

Suppress the warning by resetting the log manager:

import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.control.cell.*;
import javafx.scene.layout.*;
import javafx.beans.property.*;
import javafx.collections.*;

import java.util.logging.LogManager;

public class TableViewSample extends Application {
  // ... setup ...

  public static void main(String[] args) {

    // Suppress the warning message when the Add button is clicked.
    LogManager.getLogManager().reset();

    launch(args);
  }

This will affect the entire application's logger. If that is not desired, change the logging level for the offending class (com.sun.javafx.scene.control.skin.VirtualFlow) to Level.OFF.

See also:

Since this is a warning message, it can probably be ignored, and therefore suppressed. As far as I can tell, the new row is added successfully. Here is the offending code that was checked in, which, IMO, violates the principle of least astonishment:

Comments

Your Answer

Draft saved
Draft discarded

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.