2016-04-11 8 views
0

このコードスニペットを使用して、自分のテーブルの編集コミットを完了しました。編集テーブル用のjavafxバインディングコードスニペットが機能しません

 SimpleStringProperty sp = (SimpleStringProperty)ov; 

私はそれについて何ができるか見当もつかない: UITableView - Better Editing through Binding?

私の問題は、私はこの行の

Caused by: java.lang.ClassCastException: javafx.beans.property.ReadOnlyObjectWrapper cannot be cast to javafx.beans.property.SimpleStringProperty 

を得るということです。 私はデータクラスにSimpleStringPropertyの値を使用しています。ここで

は完全なコードです:

import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.control.ContentDisplay; 
import javafx.scene.control.TableCell; 
import javafx.scene.control.TableColumn; 
import javafx.scene.control.TextArea; 
import javafx.util.Callback; 

import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.TableView; 
import javafx.scene.control.cell.PropertyValueFactory; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 

public class Supermain extends Application { 



    @Override 
    public void start(Stage primaryStage) { 

     final TableView<myTextRow> table = new TableView<>(); 
     table.setEditable(true); 
     table.setStyle("-fx-text-wrap: true;"); 

     //Table columns 
     TableColumn<myTextRow, String> clmID = new TableColumn<>("ID"); 
     clmID.setMinWidth(160); 
     clmID.setCellValueFactory(new PropertyValueFactory<>("ID")); 


     TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text"); 
     clmtext.setMinWidth(160); 
     clmtext.setCellValueFactory(new PropertyValueFactory<>("text")); 
     clmtext.setCellFactory(new TextFieldCellFactory()); 

     //Add data 
     final ObservableList<myTextRow> data = FXCollections.observableArrayList(
       new myTextRow(5, "Lorem"), 
       new myTextRow(2, "Ipsum") 
     ); 
     table.setItems(data); 
     table.getColumns().addAll(clmID, clmtext); 

     HBox hBox = new HBox(); 
     hBox.setSpacing(5.0); 
     hBox.setPadding(new Insets(5, 5, 5, 5)); 

     Button btn = new Button(); 
     btn.setText("Get Data"); 
     btn.setOnAction(new EventHandler<ActionEvent>() { 

      @Override 
      public void handle(ActionEvent event) { 
       for (myTextRow data1 : data) { 
        System.out.println("data:"+data1.getText()); 
       } 
      } 
     }); 

     hBox.getChildren().add(btn); 


     BorderPane pane = new BorderPane(); 
     pane.setTop(hBox); 
     pane.setCenter(table); 
     primaryStage.setScene(new Scene(pane, 640, 480)); 
     primaryStage.show(); 

    } 

    /** 
    * @param args the command line arguments 
    */ 
    public static void main(String[] args) { 
     launch(args); 
    } 

    public static class TextFieldCellFactory 
      implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> { 


     @Override 
     public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) { 
      TextFieldCell textFieldCell = new TextFieldCell(); 
      return textFieldCell; 
     } 

     public static class TextFieldCell extends TableCell<myTextRow, String> { 

      private TextArea textField; 
      private StringProperty boundToCurrently = null; 


      public TextFieldCell() { 
       String strCss; 
       // Padding in Text field cell is not wanted - we want the Textfield itself to "be" 
       // The cell. Though, this is aesthetic only. to each his own. comment out 
       // to revert back. 
       strCss = "-fx-padding: 0;"; 

       this.setStyle(strCss); 

       textField = new TextArea(); 
       textField.setWrapText(true); 
       textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2); 



       //textField.setPrefHeight(real_lines_height(textField.getText(),this.getWidth(),30,23)); 
       // 
       // Default style pulled from caspian.css. Used to play around with the inset background colors 
       // ---trying to produce a text box without borders 
       strCss = "" 
         + //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" + 
         "-fx-background-color: -fx-control-inner-background;" 
         + //"-fx-background-insets: 0, 1, 2;" + 
         "-fx-background-insets: 0;" 
         + //"-fx-background-radius: 3, 2, 2;" + 
         "-fx-background-radius: 0;" 
         + // "-fx-padding: 3 5 3 5;" + /*Play with this value to center the text depending on cell height??*/ 
         "-fx-padding: 0 0 0 0;" 
         + /*Play with this value to center the text depending on cell height??*/ //"-fx-padding: 0 0 0 0;" + 
         "-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);" 
         + "-fx-cursor: text;" 
         + ""; 

       // Focused and hover states should be set in the CSS. This is just a test 
       // to see what happens when we set the style in code 
       textField.focusedProperty().addListener(new ChangeListener<Boolean>() { 
        @Override 
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 
         TextArea tf = (TextArea) getGraphic(); 
         // System.out.println(".changed() index : "+ get_ID_from_table_index(getIndex())); 

         String strStyleGotFocus = "-fx-background-color: blue, -fx-text-box-border, -fx-control-inner-background;" 
           + "-fx-background-insets: -0.4, 1, 2;" 
           + "-fx-background-radius: 3.4, 2, 2;"; 
         String strStyleLostFocus 
           = //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" + 
           "-fx-background-color: -fx-control-inner-background;" 
           + //"-fx-background-insets: 0, 1, 2;" + 
           "-fx-background-insets: 0;" 
           + //"-fx-background-radius: 3, 2, 2;" + 
           "-fx-background-radius: 0;" 
           + //"-fx-padding: 3 5 3 5;" + /**/ 
           "-fx-padding: 0 0 0 0;" 
           + /**/ //"-fx-padding: 0 0 0 0;" + 
           "-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);" 
           + "-fx-cursor: text;" 
           + ""; 
         if (newValue.booleanValue()) { 
          tf.setStyle(strStyleGotFocus); 
         } else { 
          tf.setStyle(strStyleLostFocus); 
         } 

         if(!newValue) 
         {                   


          System.out.println("EDITABLE???? "+isEditing()); 
          System.out.println("TEXT:::: "+textField.getText()); 
         // commitEdit(textField.getText()); 

         } 

        } 
       }); 
       textField.hoverProperty().addListener(new ChangeListener<Boolean>() { 

        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 

         TextArea tf = (TextArea) getGraphic(); 
         String strStyleGotHover = "-fx-background-color: derive(blue,90%), -fx-text-box-border, derive(-fx-control-inner-background, 10%);" 
           + "-fx-background-insets: 1, 2.8, 3.8;" 
           + "-fx-background-radius: 3.4, 2, 2;"; 
         String strStyleLostHover 
           = //"-fx-background-color: -fx-shadow-highlight-color, -fx-text-box-border, -fx-control-inner-background;" + 
           "-fx-background-color: -fx-control-inner-background;" 
           + //"-fx-background-insets: 0, 1, 2;" + 
           "-fx-background-insets: 0;" 
           + //"-fx-background-radius: 3, 2, 2;" + 
           "-fx-background-radius: 0;" 
           + //"-fx-padding: 3 5 3 5;" + /**/ 
           "-fx-padding: 0 0 0 0;" 
           + "-fx-prompt-text-fill: derive(-fx-control-inner-background,-30%);" 
           + "-fx-cursor: text;" 
           + ""; 
         String strStyleHasFocus = "-fx-background-color: blue, -fx-text-box-border, -fx-control-inner-background;" 
           + "-fx-background-insets: -0.4, 1, 2;" 
           + "-fx-background-radius: 3.4, 2, 2;"; 

         if (newValue.booleanValue()) { 
          tf.setStyle(strStyleGotHover); 



         } else if (!tf.focusedProperty().get()) { 
          tf.setStyle(strStyleLostHover); 
         } else { 
          tf.setStyle(strStyleHasFocus); 
         } 

        } 
       }); 

       textField.textProperty().addListener(e -> { 
        double height = 25; 
        textField.setPrefHeight(height); 
        textField.setMaxHeight(height); 


        //System.out.println("textfield Parent: "+textField.getParent().toString()); 
       }); 
       textField.setStyle(strCss); 
       this.setGraphic(textField); 
      } 

      @Override 
    protected void updateItem(String item, boolean empty) { 
     super.updateItem(item, empty);   
     if(!empty) { 
     // Show the Text Field 
     this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY); 

     // Retrieve the actual String Property that should be bound to the TextField 
     // If the TextField is currently bound to a different StringProperty 
     // Unbind the old property and rebind to the new one 
     ObservableValue<String> ov = getTableColumn().getCellObservableValue(getIndex()); 
     SimpleStringProperty sp = (SimpleStringProperty)ov; 

     if(this.boundToCurrently==null) { 
      this.boundToCurrently = sp; 
      this.textField.textProperty().bindBidirectional(sp); 
     } 
     else { 
      if(this.boundToCurrently != sp) { 
       this.textField.textProperty().unbindBidirectional(this.boundToCurrently); 
       this.boundToCurrently = sp; 
       this.textField.textProperty().bindBidirectional(this.boundToCurrently); 
      } 
     } 
     System.out.println("item=" + item + " ObservableValue<String>=" + ov.getValue()); 
     //this.textField.setText(item); // No longer need this!!! 
     } 
     else { 
     this.setContentDisplay(ContentDisplay.TEXT_ONLY); 
     } 
    } 

     } 


    } 

    public class myTextRow { 

     private final SimpleIntegerProperty ID; 

     private final SimpleStringProperty text; 

     public myTextRow(int ID, String text) { 

      this.ID = new SimpleIntegerProperty(ID); 
      this.text = new SimpleStringProperty(text); 

     } 

     public void setID(int id) { 
      this.ID.set(id); 
     } 

     public void setText(String text) { 
      this.text.set(text); 
     } 

     public int getID() { 
      return ID.get(); 
     } 

     public String getText() { 
      return text.get(); 
     } 
    } 
} 
+0

あなたがキャストしているもの( 'ov')が' SimpleStringProperty'ではないことは明らかです。 'ReadOnlyObjectWrapper'です。あなたの質問を編集して[MCVE]を提供できますか? –

+0

スニペットを含む完全なコードを他のstackO質問からアップロードします。 – user3776738

答えて

1

あなたのモデルクラスは「プロパティアクセサを」がありません。したがって、プロパティ自体はPropertyValueFactoryでは使用できません。 PropertyValueFactory documentationで述べたようにこのクラスを使用する方法の

例である:

TableColumn<Person,String> firstNameCol = new TableColumn<Person,String>("First Name"); 
firstNameCol.setCellValueFactory(new PropertyValueFactory<Person,String>("firstName")); 
この例で

"firstName"ストリングはで想定 firstNameProperty()方法基準として使用されますPersonクラスタイプ(これは、TableViewアイテムリストの クラスタイプです)。さらに、このメソッド はPropertyインスタンスを返す必要があります。これらの条件を満たすメソッドが見つかった場合、TableCellには ObservableValueが設定されます。さらに、TableViewは、 オブザーバを戻り値に自動的に追加します。その結果、変更された変更はTableViewによって観察される になり、セルが直ちに更新されます。このパターンに一致する方法が存在しない場合

は、(取得呼び出そうとするためのフォールスルー 支持体)が存在する、または)である(( は、上記の例では、getFirstName()又はisFirstName()あること)。このパターンに一致するメソッド が存在する場合、このメソッドから返される値は がReadOnlyObjectWrapperにラップされ、TableCellに返されます。

textProperty()またはiDProperty()メソッドがモデルクラスに定義されていないため、最後の段落で状況を正確に説明しています。したがってPropertyValueFactoryは実際のプロパティインスタンスを返す代わりにReadOnlyObjectWrapperを作成して返します。

idカラムに間違ったタイプがあることにも注意してください。プロパティはIntegerPropertyです。これはProperty<String>ではなく、Property<Number>です。したがって、そのテーブルの列はTableColumn<myTextRow, Number>である必要があります。これは、テキストフィールド内の文字列とidの値であるIntegerとの間で変換する必要があるので、テーブルセルの実装を使用するのはかなり面倒です。しかし一般的には

、次のようにJavaFX Property pattern次クラスを記述します。

public class myTextRow { 

    private final IntegerProperty id; 

    private final StringProperty text; 

    public myTextRow(int ID, String text) { 

     this.id = new SimpleIntegerProperty(ID); 
     this.text = new SimpleStringProperty(text); 

    } 

    public void setId(int id) { 
     this.id.set(id); 
    } 

    public void setText(String text) { 
     this.text.set(text); 
    } 

    public int getId() { 
     return id.get(); 
    } 

    public String getText() { 
     return text.get(); 
    } 

    public StringProperty textProperty() { 
     return text; 
    } 

    public IntegerProperty idProperty() { 
     return id ; 
    } 
} 

、その後、あなたが

TableColumn<myTextRow, Number> clmID = new TableColumn<>("ID"); 
clmID.setMinWidth(160); 
clmID.setCellValueFactory(new PropertyValueFactory<>("id")); 


TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text"); 
clmtext.setMinWidth(160); 
clmtext.setCellValueFactory(new PropertyValueFactory<>("text")); 

か、作るた(ラムダ式を使用して、あなたのセルの値ファクトリを定義することができますがコンパイラは正しいメソッドの存在をチェックできます)。

TableColumn<myTextRow, Number> clmID = new TableColumn<>("ID"); 
clmID.setMinWidth(160); 
clmID.setCellValueFactory(cellData -> cellData.getValue().idProperty()); 


TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text"); 
clmtext.setMinWidth(160); 
clmtext.setCellValueFactory(cellData -> cellData.getValue().textProperty()); 
関連する問題