2013-10-04 11 views
5

Poniższy program działa poprawnie, jeśli linia value.setCellFactory(NUMBER_CELL_FACTORY); została skomentowana.Treść pojawia się w pustych wierszach z niestandardową fabryką komórek

Jeśli jednak jest uwzględniony, TableView zachowuje się dziwnie * - po prostu skopiuj kod, uruchom go i kliknij kilka razy na przycisku +, zobaczysz zawartość pojawiającą się w pustych wierszach u dołu tabeli.

Czy brakuje mi czegoś?

* Testowany na 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); 
     } 
    } 
} 

Odpowiedz

6

Próbowałem swój przykładowy program na Win7 Java7b108 i wydawało się działać dobrze z NumberTableCell, jednak nadal ma problem.

Problem polega na tym, że komórki są ponownie wykorzystywane, więc jeśli komórka staje się pusta z jakiegokolwiek powodu, należy wyczyścić wszelkie niestandardowe wartości ustawione w komórce, aby renderować ją jak domyślną pustą komórkę. Poniższy kod pokazuje jak to zrobić:

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

Oto mała aktualizacja do programu, który łatwiej replikuje problem i pokazuje poprawkę. Jeśli skomentujesz linie setText (null) i setTextFill (null), a następnie naciśnij przycisk + kilka razy, a następnie zacznij naciskać przycisk -, zobaczysz, że TableView tak naprawdę nie odzwierciedla stanu podstawowej listy. Ale z ustawionymi zerami wszystko jest poprawnie zsynchronizowane. To jest ...

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); 
     } 
    } 
} 
Powiązane problemy