This discussion is archived
4 Replies Latest reply: Feb 26, 2013 8:57 AM by B. Soidik RSS

Just an exception when updating TableView Cell

B. Soidik Newbie
Currently Being Moderated
Hi!
I have a TableVew whith two clumns, and I have two TextField, and I display a bean Personne who has two string properties, when I select a row I bind it with TextFields, and I unbind olds, but, and when I edit Textfields cells must be updated automaticaly. But I have an ClassCastException when runnig aplication it says javafx.beans.property.ReadOnlyObjectWrapper cannot be cast to javafx.beans.property.SimpleStringProperty.
It gives :
SEVERE: javafx.scene.control.Control loadSkinClass Failed to load skin 'StringProperty [bean: TableView[id=null, styleClass=table-view], name: skinClassName, value: com.sun.javafx.scene.control.skin.TableViewSkin]' for control TableView[id=null, styleClass=table-view]
java.lang.ClassCastException: javafx.beans.property.ReadOnlyObjectWrapper cannot be cast to javafx.beans.property.SimpleStringProperty
     at testappl.TestAppl$CelluleAjour.updateItem(TestAppl.java:49)
     at testappl.TestAppl$CelluleAjour.updateItem(TestAppl.java:39)
.....
>

This is the code of main class
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testappl;


import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Callback;


 
public class TestAppl extends Application {
 
  private TableView<Personne> tv;
  private TextField tfNom;
  private TextField tfPrenom;
  private ObservableList<Personne> personnes;
  //La personne sléctioné
  private Personne pEnCours;
  
  
  
   public static class CelluleAjour extends TableCell<Personne,String> {        
        private StringProperty boundToCurrently = null;

      @Override
          protected void updateItem(String item, boolean empty) {
          super.updateItem(item, empty);        
          if(!empty) {
         
           ObservableValue ov = getTableColumn().getCellObservableValue(getIndex());
           
           SimpleStringProperty sp = (SimpleStringProperty) ov;

            if(this.boundToCurrently==null) {
                this.boundToCurrently = sp;
                this.textProperty().bind(sp);
            }
            else {
                if(this.boundToCurrently != sp) {
                  this.textProperty().unbind();
                  this.boundToCurrently = sp;
                  this.textProperty().bind(boundToCurrently);
                }
            }   
          }}
   }
  
  @Override
  public void start(Stage primaryStage) throws Exception {
    primaryStage.setTitle("Test de TableView");
 
    Scene scene = new Scene(new BorderPane(), 800, 500);
    primaryStage.setScene(scene);
    HBox pan = new HBox();
    pan.setPadding(new Insets(10, 10, 10, 10));
    pan.setSpacing(5);
    tfNom = new TextField();
    tfPrenom = new TextField();
 
    pan.getChildren().addAll(tfNom, tfPrenom);
    ((BorderPane) scene.getRoot()).setTop(pan);
 
    tv = new TableView<>();
 
    TableColumn nomCol = new TableColumn("Nom");
    nomCol.setCellValueFactory(new PropertyValueFactory("nom"));
    nomCol.setCellFactory(new Callback<TableColumn, TableCell>() {
 
                    @Override
                    public TableCell call(TableColumn p) {
                        return new TestAppl.CelluleAjour();
                    }
                });
    TableColumn prenomCol = new TableColumn("Prénom");
    prenomCol.setCellValueFactory(new PropertyValueFactory("prenom"));
    prenomCol.setCellFactory(new Callback<TableColumn, TableCell>() {
 
                    @Override
                    public TableCell call(TableColumn p) {
                        return new TestAppl.CelluleAjour();
                    }
                });
    
    tv.getColumns().addAll(nomCol, prenomCol);
 
    personnes = FXCollections.observableArrayList(new Personne("Nom1", "prenom1"),
                                                  new Personne("Nom2", "prenom2"),
                                                  new Personne("Nom3", "prenom3"));
    tv.getItems().addAll(personnes);
    tv.setOnMouseClicked(new EventHandler<MouseEvent>() {
      @Override
        public void handle(MouseEvent mouseEvent) {
          if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
            if (mouseEvent.getClickCount() == 1) {
                
               if(pEnCours!=null){
                
                tfNom.textProperty().unbindBidirectional(pEnCours.NomProperty());
                tfPrenom.textProperty().unbindBidirectional(pEnCours.PrenomProperty());     
                }
                pEnCours=tv.getSelectionModel().getSelectedItem();
                //Attribuer de nouveaux liens 
                tfNom.textProperty().bindBidirectional(pEnCours.NomProperty());
                tfPrenom.textProperty().bindBidirectional(pEnCours.PrenomProperty());

          }
        }
      }
    });
 
    ((BorderPane) scene.getRoot()).setCenter(tv);
 
    primaryStage.show();
  }
 
  public static void main(String[] args) {
    Application.launch(args);
  }
}
The bean Personne:
 
package testappl;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;


/**
 *
 * @author bilalsoidik
 */
public class Personne {
   
    private StringProperty nom;
    private StringProperty prenom;
    

 public Personne(String nom, String prenom){
 this.nom=new SimpleStringProperty(nom);
 this.prenom=new SimpleStringProperty(prenom);
 }
    public final String getNom() {
      return nom.get();
    }
 
    public final void setNom(String nom) {
      this.nom.set(nom);
    }
    public StringProperty NomProperty(){
        return nom;
        
    }
            
    public final String getPrenom() {
      return prenom.get();
    }
 
    public final void setPrenom(String prenom) {
      this.prenom.set(prenom);
    }
   public StringProperty PrenomProperty(){
   return prenom;}
  }
Thanks
  • 1. Re: Just an exception when updating TableView Cell
    James_D Guru
    Currently Being Moderated
    You don't need the custom cell implementation if you use the default naming scheme for your properties.

    In the Personne class, change the method names NomProperty() to nomProperty() and PrenomProperty() to prenomProperty(), and make the corresponding changes to the mouse listener for the table. The problem as you have it is that the default cell implementation can't find a property called "nom" (i.e. a nomProperty() method), so it is resorting to calling getNom() and wrapping the result in a ReadOnlyObjectWrapper.

    Then remove the CelluleAjour class entirely and the two calls to setCellFactory(...) and it will work.

    (You could instead change new PropertyCellFactory("nom") to new PropertyCellFactory("Nom"), and similarly for the other column, but the first way is more standard.)

    So it should look like this:
    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.event.EventHandler;
    import javafx.geometry.Insets;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.control.cell.PropertyValueFactory;
    import javafx.scene.input.MouseButton;
    import javafx.scene.input.MouseEvent;
    import javafx.scene.layout.BorderPane;
    import javafx.scene.layout.HBox;
    import javafx.stage.Stage;
    
    public class TestAppl extends Application {
    
      private TableView<Personne> tv;
      private TextField tfNom;
      private TextField tfPrenom;
      private ObservableList<Personne> personnes;
    
      private Personne pEnCours;
    
      @Override
      public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Test de TableView");
    
        Scene scene = new Scene(new BorderPane(), 800, 500);
        primaryStage.setScene(scene);
        HBox pan = new HBox();
        pan.setPadding(new Insets(10, 10, 10, 10));
        pan.setSpacing(5);
        tfNom = new TextField();
        tfPrenom = new TextField();
    
        pan.getChildren().addAll(tfNom, tfPrenom);
        ((BorderPane) scene.getRoot()).setTop(pan);
    
        tv = new TableView();
    
        TableColumn nomCol = new TableColumn("Nom");
        nomCol.setCellValueFactory(new PropertyValueFactory("nom"));
    
        TableColumn prenomCol = new TableColumn("Prénom");
        prenomCol.setCellValueFactory(new PropertyValueFactory("prenom"));
    
        tv.getColumns().addAll(nomCol, prenomCol);
    
        personnes = FXCollections.observableArrayList(new Personne("Nom1",
            "prenom1"), new Personne("Nom2", "prenom2"), new Personne("Nom3",
            "prenom3"));
        tv.getItems().addAll(personnes);
        tv.setOnMouseClicked(new EventHandler<MouseEvent>() {
          @Override
          public void handle(MouseEvent mouseEvent) {
            if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
              if (mouseEvent.getClickCount() == 1) {
    
                if (pEnCours != null) {
    
                  tfNom.textProperty().unbindBidirectional(pEnCours.nomProperty());
                  tfPrenom.textProperty().unbindBidirectional(
                      pEnCours.prenomProperty());
                }
                pEnCours = tv.getSelectionModel().getSelectedItem();
                // Attribuer de nouveaux liens
                tfNom.textProperty().bindBidirectional(pEnCours.nomProperty());
                tfPrenom.textProperty()
                    .bindBidirectional(pEnCours.prenomProperty());
    
              }
            }
          }
        });
    
        ((BorderPane) scene.getRoot()).setCenter(tv);
    
        primaryStage.show();
      }
    
      public static void main(String[] args) {
        Application.launch(args);
      }
    }
    and
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
    
    /**
     * 
     * @author bilalsoidik
     */
    public class Personne {
    
      private StringProperty nom;
      private StringProperty prenom;
    
      public Personne(String nom, String prenom) {
        this.nom = new SimpleStringProperty(nom);
        this.prenom = new SimpleStringProperty(prenom);
      }
    
      public final String getNom() {
        return nom.get();
      }
    
      public final void setNom(String nom) {
        this.nom.set(nom);
      }
    
      public StringProperty nomProperty() {
        return nom;
    
      }
    
      public final String getPrenom() {
        return prenom.get();
      }
    
      public final void setPrenom(String prenom) {
        this.prenom.set(prenom);
      }
    
      public StringProperty prenomProperty() {
        return prenom;
      }
    }
  • 2. Re: Just an exception when updating TableView Cell
    shakir.gusaroff Expert
    Currently Being Moderated
    Hi. Try the following:
           //ObservableValue ov = getTableColumn().getCellObservableValue(getIndex());
           //SimpleStringProperty sp = (SimpleStringProperty) ov;
           SimpleStringProperty sp =  new SimpleStringProperty(getTableColumn().getCellObservableValue(getIndex()).getValue()); 
    Edited by: shakir.gusaroff on Feb 26, 2013 7:34 AM
  • 3. Re: Just an exception when updating TableView Cell
    James_D Guru
    Currently Being Moderated
    Shakir:

    That's doesn't actually work, does it? In the sense that it doesn't bind bidirectionally to the property of the selected row in the table?
  • 4. Re: Just an exception when updating TableView Cell
    B. Soidik Newbie
    Currently Being Moderated
    Thank you verry mach, that is working correctely :)

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points