如何正确地向TableView添加新数据并滚动到它

时间:2015-04-18 07:21:15

标签: javafx tableview

问题

我想动态地向TableView添加数据并滚动到新数据的位置。但是当TableView中的行达到ViewPort大小时,我会在控制台中看到它:

  

2015年4月18日上午9:14:34 com.sun.javafx.scene.control.skin.VirtualFlow   addTrailingCells INFO:index超过maxCellCount。检查尺寸   类javafx.scene.control.TableRow

的计算

所以我猜我做错了什么。我所做的只是使用Oracle TableView示例并添加:

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

});

使用

时会发生同样的情况
    table.getItems().add( person);

而不是修改列表。

罪魁祸首是scrollTo方法。将行索引与scrollTo方法一起使用时会出现相同的信息/错误。

问题

如何正确地向TableView添加新项目,以便不显示信息/错误?

代码

这是一个完整的例子。该表已预先填写。如果按“添加”按钮,则达到视口大小,并在控制台中显示信息(或错误?)。

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 个答案:

答案 0 :(得分:0)

通过重置日志管理器来禁止警告:

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

这会影响整个应用程序的记录器。如果不需要,请将违规类(com.sun.javafx.scene.control.skin.VirtualFlow)的日志记录级别更改为Level.OFF

另见:

由于这是一条警告消息,因此可能会被忽略,因此会被抑制。据我所知,新行已成功添加。以下是签入的违规代码,IMO违反了最不惊讶的原则:

答案 1 :(得分:0)

我使用固定单元格解决了这个问题。

listCategory.setFixedCellSize(40); 

-fx-fixed-cell-size : 40;

答案 2 :(得分:-1)

我之前有过这样的警告,但是你不必担心,因为提到here

  

当需要的最大额外单元数时会发生这种情况   如果每个单元格的高度为1,则能够适合视口。   如果index超过此计数,则offset不会快速递增   足够的,或者根本就是,这意味着细胞有问题   尺寸计算。(第2.48行:

这可能是由我们造成的,因为我们的滚动速度比普通用户或RC代码中的其他内容更快,而示例中的 如果你有很多行,> table.scrollTo( person); 滚动得更快

答案 3 :(得分:-1)

我没有找到解决方案,但问题不在于使用scrollTo()方法,当你滚动到底部(甚至手动)时总会发生这种情况,当滚动消失时增加窗口高度我不知道为什么需要打开一张错误票