2015-05-05 71 views
2

我有一個可編輯的TableView,其中添加了一個新行,然後調用該行第一列的table.edit()。當用戶想添加一個將不在視口中的行時,會發生什麼情況是表在視口中滾動新行並開始編輯。但是,調用table.scrollTo(newRow)會導致各種錯誤行爲。該行被引入視圖,但只有一些時間進入編輯。最可能發生的情況是視口中的第一行開始編輯,而不是新添加的行。這種情況發生在將被添加到視圖中的行以及不在視圖中的行上。JavaFX TableView scrollTo()導致錯誤的行開始編輯

我的代碼:

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。我已經嘗試了方法調用和可運行的順序的每個組合,我可以用相同的結果來考慮。如果有人能幫助我,我會很感激。

回答

5

,似乎工作,儘管我有沒有它的解釋是完全隨機的黑客:

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

你不需要Platform.runLater(...)與此有關。我會file a bug這一點,雖然,因爲隨機的黑客不應該是必要的...

這個靈感來自於Uluk BIY的回答this question

+0

的問題似乎是一個電池的壽命是不明確(根本不指定) - 啓發式顯示它是在虛擬流的所有者的調用佈局上創建的。這很好(添加/編輯項目後)。這是一個框架無法應對的錯誤(https://javafx-jira.kenai.com/browse/RT-40661),另請參閱http://stackoverflow.com/q/29863095/203657。 – kleopatra