【问题标题】:JavaFX TableView scrollTo() causing wrong row to start editingJavaFX TableView scrollTo() 导致错误的行开始编辑
【发布时间】:2015-07-15 15:49:56
【问题描述】:

我有一个可编辑的 TableView,它带有一个添加新行的按钮,然后在该行的第一列上调用 table.edit()。当用户想要添加将超出视口的行时,应该发生的是表格在视口内滚动新行并开始编辑。但是,调用 table.scrollTo(newRow) 会导致各种错误行为。该行显示在视图中,但只有部分时间进入编辑状态。似乎发生得最多的是视口中的第一行开始编辑,而不是新添加的行。这发生在将被添加到视图中的行以及将不在视图中的行上。

我的代码:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableColumn.CellEditEvent;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;


public class TableViewScrollToTest extends Application {

    private final TableView<Person> table = new TableView<>();
    private final ObservableList<Person> data = FXCollections.observableArrayList();
    private final HBox hb = new HBox();
    private final Button addButton = new Button("_Add");
    private int seq = 0;

    @Override
    public void start(Stage primaryStage) throws Exception {
        Scene scene = new Scene(new Group());
        primaryStage.setTitle("Table View Scroll To Test");
        primaryStage.setWidth(450);
        primaryStage.setHeight(300);

        table.setEditable(true);

        TableColumn<Person, String> firstNameCol = new TableColumn<>("First Name");
        firstNameCol.setMinWidth(100);
        firstNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("firstName"));
        firstNameCol.setCellFactory(TextFieldTableCell.<Person> forTableColumn());
        firstNameCol.setOnEditCommit((CellEditEvent<Person, String> event) -> {
            event.getRowValue().setFirstName(event.getNewValue());
        });

        TableColumn<Person, String> lastNameCol = new TableColumn<>("Last Name");
        lastNameCol.setMinWidth(100);
        lastNameCol.setCellValueFactory(new PropertyValueFactory<Person, String>("lastName"));
        lastNameCol.setCellFactory(TextFieldTableCell.<Person> forTableColumn());
        lastNameCol.setOnEditCommit((CellEditEvent<Person, String> event) -> {
            event.getRowValue().setLastName(event.getNewValue());
        });

        TableColumn<Person, String> emailCol = new TableColumn<>("Email");
        emailCol.setMinWidth(200);
        emailCol.setCellValueFactory(new PropertyValueFactory<Person, String>("email"));
        emailCol.setCellFactory(TextFieldTableCell.<Person> forTableColumn());
        emailCol.setOnEditCommit((CellEditEvent<Person, String> event) -> {
            event.getRowValue().setEmail(event.getNewValue());
        });

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

        addButton.setOnAction(event -> {
            table.getSelectionModel().clearSelection();
            Person p = new Person("First Name", "Last Name " + seq++, "");
            data.add(p);
            table.getSelectionModel().select(p);
            Platform.runLater(() -> {
                table.scrollTo(p); //causes buggy behavior
                table.edit(data.indexOf(p), firstNameCol);
            });
        });

        hb.getChildren().add(addButton);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        vbox.setPadding(new Insets(10, 0, 0, 10));
        vbox.getChildren().addAll(table, hb);

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

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static class Person {

        private StringProperty firstName;
        private StringProperty lastName;
        private StringProperty email;

        public Person(String first, String last, String email) {
            firstName = new SimpleStringProperty(this, "firstName", first);
            lastName = new SimpleStringProperty(this, "lastName", last);
            this.email = new SimpleStringProperty(this, "email", email);
        }

        public void setFirstName(String value) { firstNameProperty().set(value); }
        public String getFirstName() { return firstNameProperty().get(); }
        public StringProperty firstNameProperty() { 
            if (firstName == null) firstName = new SimpleStringProperty(this, "firstName", "First");
            return firstName; 
        }

        public void setLastName(String value) { lastNameProperty().set(value); }
        public String getLastName() { return lastNameProperty().get(); }
        public StringProperty lastNameProperty() { 
            if (lastName == null) lastName = new SimpleStringProperty(this, "lastName", "Last");
            return lastName; 
        } 

        public void setEmail(String value) { emailProperty().set(value); }
        public String getEmail() { return emailProperty().get(); }
        public StringProperty emailProperty() {
            if(email == null) {
                email = new SimpleStringProperty(this, "email", "");
            }
            return email;
        }
    }

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

如果您注释掉 table.scrollTo(),添加然后编辑行可以正常工作。我尝试了https://stackoverflow.com/a/27786741/3050379,但即使正在添加的行在视图中,isIndexVisible() 有时也会返回 false。我已经尝试了所有我能想到的方法调用顺序和可运行对象的组合,结果相同。如果有人可以帮助我,我将不胜感激。

【问题讨论】:

    标签: tableview javafx-8 scrollto


    【解决方案1】:

    完全随机的 hack 似乎有效,尽管我对此没有任何解释:

        table.scrollTo(p); 
        table.layout();
        table.edit(data.indexOf(p), firstNameCol);
    

    你不需要Platform.runLater(...)。不过,我会为此file a bug,因为不需要随机破解...

    这是受到 Uluk Biy 对 this question 的回答的启发

    【讨论】:

    • 问题似乎是单元格的生命周期定义不明确(根本没有指定) - 启发式表明它是在调用 virtualFlow 所有者的布局时创建的。那是在添加/编辑项目之后(未知延迟)。这是框架无法应对的错误 (javafx-jira.kenai.com/browse/RT-40661),另请参阅 stackoverflow.com/q/29863095/203657
    • 仅供参考:fx17 似乎正在工作(不需要调用布局,也不需要像 OP 的代码那样运行) - 最近有一些改进 :) 顺便说一句:我链接的问题的报告参考在我的最后一条评论中现在是bugs.openjdk.java.net/browse/JDK-8089497
    猜你喜欢
    • 1970-01-01
    • 2018-09-06
    • 1970-01-01
    • 2014-10-19
    • 2012-10-05
    • 2014-10-14
    • 1970-01-01
    • 2017-01-23
    相关资源
    最近更新 更多