JavaFX TableView scrollTo()导致错误的行开始编辑 [英] JavaFX TableView scrollTo() causing wrong row to start editing

查看:79
本文介绍了JavaFX TableView scrollTo()导致错误的行开始编辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an editable TableView with a button that adds a new row then calls table.edit() on the first column in that row. When a user wants to add a row that will be out of the viewport, what should happen is the table scrolls the new row within the viewport and starts editing. However, calling table.scrollTo(newRow) causes all sorts of buggy behavior. The row is brought into view, but only some of the time goes into editing. What seems to happen the most is the first row within the viewport starts editing rather than the newly added row. This happens on rows that would be added in view as well as rows that would be out of view.

我的代码:

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 ,但即使正在添加的行在视图中.我已经尝试过方法调用和可运行对象的顺序的所有组合,这些组合我都可以想到,它们的结果相同.如果有人可以帮助我,我将非常感激.

If you comment out the table.scrollTo(), adding then editing the row works fine. I tried https://stackoverflow.com/a/27786741/3050379 but isIndexVisible() returns false at times even when the row being added is in view. I've tried every combination of the order of method calls and runnables that I could think of with the same result. If anyone could help me out, I would really appreciate it.

推荐答案

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

Completely random hack that seems to work, despite me having no explanation for it:

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

您不需要Platform.runLater(...).不过,我会为此提交错误有必要...

You don't need the Platform.runLater(...) with this. I would file a bug for this, though, as the random hack should not be necessary...

这是受到Uluk Biy对此问题的回答

This was inspired by Uluk Biy's answer to this question

这篇关于JavaFX TableView scrollTo()导致错误的行开始编辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆