How to correctly add new data to TableView and scr

2020-02-13 17:34发布

问题:

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);
        }
    }
} 

回答1:

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:

  • http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8140504
  • http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8089472

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:

  • http://hg.openjdk.java.net/openjfx/8u-dev/rt/rev/92396a5f81f2#l2.60


回答2:

I solved this problem using fixed cells..

listCategory.setFixedCellSize(40); 

or

-fx-fixed-cell-size : 40;


回答3:

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



回答4:

I had this warning before but you don't have to worry about it beause as mentioned here:

This happens when the maximum number of additional cells that should ever be able to fit in the viewport if every cell had a height of 1. If index ever exceeds this count, then offset is not incrementing fast enough, or at all, which means there is something wrong with the cell size calculation.(in line 2.48:)

This might be caused by us, because we scroll faster than the average user or other things in the RC-code and in your example table.scrollTo( person); do scroll even faster specially if you had much rows.