2013-10-04 1 views
5

Le programme ci-dessous fonctionne correctement si la ligne value.setCellFactory(NUMBER_CELL_FACTORY); est mise en commentaire. S'il est inclus cependant, le TableView se comportera bizarrement * - si vous copiez simplement le code, le lancez et cliquez plusieurs fois sur le bouton +, vous verrez le contenu apparaître dans des rangées vides au bas de la table.Le contenu apparaît dans des lignes vides avec une fabrique de cellules personnalisée

Est-ce que je manque quelque chose?

* Testé sur JavaFx 8 - b106.

import javafx.application.Application; 
import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.AnchorPane; 
import javafx.scene.layout.VBox; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class TestFX extends Application { 

    @Override 
    public void start(final Stage stage) throws Exception { 
     MyTable table = new MyTable(); 

     Scene scene = new Scene(table); 

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

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

    static class MyTable extends AnchorPane { 

     private static final Callback NUMBER_CELL_FACTORY = (p) -> new NumberTableCell<>(); 

     private final Button addRow = new Button("+"); 
     private final TableView<Item> table = new TableView<>(); 

     MyTable() { 
      super(); 
      initTableView(); 
      addRow.setOnMouseClicked((e) -> addItem()); 
      VBox vbox = new VBox(); 
      vbox.getChildren().addAll(addRow, table); 
      getChildren().add(vbox); 
     } 

     public void addItem() { 
      table.getItems().addAll(new Item()); 
     } 

     private void initTableView() { 
      TableColumn<Item, Double> value = new TableColumn<>("Value"); 
      value.setCellValueFactory(new PropertyValueFactory<>("value")); 
      value.setCellFactory(NUMBER_CELL_FACTORY); 

      table.getColumns().add(value); 
      table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); 
     } 
    } 

    public static class Item { 
     private final DoubleProperty value = new SimpleDoubleProperty(); 

     public DoubleProperty valueProperty() { 
      return value; 
     } 
    } 

    static class NumberTableCell<T> extends TableCell<T, Double> { 
     private final Color fill = Color.LIGHTGREY; 

     @Override 
     protected void updateItem(Double item, boolean empty) { 
      super.updateItem(item, empty); 
      if (empty) return; 
      setText(String.valueOf(item)); 
      setTextFill(fill); 
     } 
    } 
} 

Répondre

6

J'ai essayé votre exemple de programme sur Win7 Java7b108 et il semblait bien fonctionner avec le NumberTableCell, mais il a encore un problème. Le problème est que les cellules sont réutilisées. Par conséquent, si une cellule est vide pour une raison quelconque, vous devez effacer toutes les valeurs personnalisées que vous avez définies dans la cellule pour qu'elles se comportent comme une cellule vide par défaut. Le code ci-dessous montre comment faire:

@Override 
    protected void updateItem(Double item, boolean empty) { 
     super.updateItem(item, empty); 
     if (empty || item == null) { 
      setText(null); 
      setTextFill(null); 
      return; 
     } 
     setText(String.valueOf(item)); 
     setTextFill(fill); 
    } 

Voici une petite mise à jour de votre programme qui reproduit plus facilement la question et démontre le correctif. Si vous commentez les lignes setText (null) et setTextFill (null), appuyez sur le bouton + plusieurs fois, puis commencez à appuyer sur le bouton -, vous verrez que TableView ne reflète pas vraiment l'état de la liste sous-jacente. Mais avec les setters nuls là-bas, tout est correctement synchronisé. C'est un gotcha ...

import javafx.application.Application; 
import javafx.beans.property.*; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.*; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.AnchorPane; 
import javafx.scene.layout.VBox; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class TestFX extends Application { 

    @Override 
    public void start(final Stage stage) throws Exception { 
     MyTable table = new MyTable(); 

     System.getProperties().list(System.out); 

     Scene scene = new Scene(table); 

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

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

    static class MyTable extends AnchorPane { 

     private static final Callback NUMBER_CELL_FACTORY = (p) -> new NumberTableCell<>(); 

     private final Button addRow = new Button("+"); 
     private final Button removeRow = new Button("-"); 
     private final TableView<Item> table = new TableView<>(); 

     MyTable() { 
      super(); 
      initTableView(); 
      addRow.setOnMouseClicked((e) -> addItem()); 
      removeRow.setOnMouseClicked((e) -> removeItem()); 
      VBox vbox = new VBox(5); 
      vbox.getChildren().addAll(addRow, removeRow, table); 
      getChildren().add(vbox); 
     } 

     public void addItem() { 
      table.getItems().addAll(new Item()); 
     } 

     public void removeItem() { 
      if (table.getItems().size() > 0) { 
       table.getItems().remove(0); 
      } 
     } 

     private void initTableView() { 
      TableColumn<Item, Double> value = new TableColumn<>("Value"); 
      value.setCellValueFactory(new PropertyValueFactory<>("value")); 
      value.setCellFactory(NUMBER_CELL_FACTORY); 

      table.getColumns().add(value); 
      table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); 
     } 
    } 

    public static class Item { 
     private final DoubleProperty value = new SimpleDoubleProperty(); 

     public DoubleProperty valueProperty() { 
      return value; 
     } 
    } 

    static class NumberTableCell<T> extends TableCell<T, Double> { 
     private final Color fill = Color.LIGHTGREY; 

     @Override 
     protected void updateItem(Double item, boolean empty) { 
      super.updateItem(item, empty); 
      if (empty || item == null) { 
       setText(null); 
       setTextFill(null); 
       return; 
      } 
      setText(String.valueOf(item)); 
      setTextFill(fill); 
     } 
    } 
} 
Questions connexes