2017-08-24 8 views
0

カスタムセルコントロールでツリーテーブルを実装しましたが、セルコントロールから更新されたデータを永続させるのに問題があります。 具体的には、commitEdit、updateControlを呼び出す方法、またはオブジェクトバインディングを使用して、各セルの変更を基底のドメインオブジェクトに確実に保持する方法があります。カスタムコントロールを使用してjavafx treetablecellsの値を永続化する方法

最初の質問に私のコードでMultiple Controls needed in JavaFX Tree Table Cell

あなたは問題が崩壊したときに、セルのデータを保持し、ツリーテーブルノードを展開を見ることができるの下に。

カスタムセルコントロールを使用して更新をトリガーし、データを基になる行オブジェクトに永続化するにはどうすればよいですか?

import java.util.Arrays; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

import javafx.application.Application; 
import javafx.beans.property.SimpleStringProperty; 
import javafx.beans.property.StringProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.beans.value.ObservableValue; 
import javafx.scene.Scene; 
import javafx.scene.control.CheckBox; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.Control; 
import javafx.scene.control.TextField; 
import javafx.scene.control.TreeItem; 
import javafx.scene.control.TreeTableCell; 
import javafx.scene.control.TreeTableColumn; 
import javafx.scene.control.TreeTableView; 
import javafx.scene.control.cell.TreeItemPropertyValueFactory; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 
import javafx.util.Callback; 
import javafx.util.converter.BooleanStringConverter; 

public class SampleApp extends Application { 

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

@SuppressWarnings("unchecked") 
@Override 
public void start(Stage primaryStage) throws Exception { 
    TreeItem<MyField> fooFields = new TreeItem<MyField>(new MyField("Foo", "Foo", null, false, null)); 
    TreeItem<MyField> fooText = new TreeItem<MyField>(new MyField("fooText", "fooText", "text", true, null)); 
    TreeItem<MyField> fooCheck = new TreeItem<MyField>(new MyField("fooCheck", "fooCheck", "check", true, null)); 
    List<String> fooCombos = Arrays.asList("foo Combo 1", "foo Combo 2"); 
    TreeItem<MyField> fooCombo = new TreeItem<MyField>(
      new MyField("fooCombo", "foo Combo", "combo", true, fooCombos)); 
    fooFields.getChildren().addAll(fooText, fooCheck, fooCombo); 

    TreeItem<MyField> barFields = new TreeItem<MyField>(new MyField("Bar", "Bar", null, false, null)); 
    TreeItem<MyField> barText = new TreeItem<MyField>(new MyField("barText", "barText", "text", true, null)); 
    TreeItem<MyField> barCheck = new TreeItem<MyField>(new MyField("barCheck", "barCheck", "check", true, null)); 
    List<String> barCombos = Arrays.asList("bar Combo 1", "bar Combo 2"); 
    TreeItem<MyField> barCombo = new TreeItem<MyField>(
      new MyField("barCombo", "bar Combo", "combo", true, barCombos)); 
    barFields.getChildren().addAll(barText, barCheck, barCombo); 

    TreeItem<MyField> hiddenRoot = new TreeItem<MyField>(new MyField("hidden", "hidden", null, false, null)); 
    hiddenRoot.getChildren().addAll(fooFields, barFields); 

    TreeTableView<MyField> treeTable = new TreeTableView<>(hiddenRoot); 
    treeTable.setEditable(true); 
    treeTable.setPrefWidth(400); 
    treeTable.setShowRoot(false); 

    TreeTableColumn<MyField, String> nameCol = new TreeTableColumn<MyField, String>("Name"); 
    nameCol.setPrefWidth(150); 
    nameCol.setCellValueFactory(new TreeItemPropertyValueFactory<MyField, String>("name")); 

    TreeTableColumn<MyField, String> valueCol = new TreeTableColumn<MyField, String>("Value"); 
    valueCol.setPrefWidth(250); 
    valueCol.setCellValueFactory(new TreeItemPropertyValueFactory<MyField, String>("value")); 
    valueCol.setCellFactory(new MyFieldCellFactory()); 

    treeTable.getColumns().addAll(nameCol, valueCol); 

    HBox root = new HBox(treeTable); 
    root.setStyle("-fx-padding: 10;" + "-fx-border-style: solid inside;" + "-fx-border-width: 2;" 
      + "-fx-border-insets: 5;" + "-fx-border-radius: 5;" + "-fx-border-color: blue;"); 
    Scene scene = new Scene(root); 
    primaryStage.setScene(scene); 
    primaryStage.setTitle("Multi Control Tree Table View"); 
    primaryStage.show(); 
} 

public class MyField { 
    private String name; 
    private StringProperty value; 
    public String fieldType; 
    public boolean isEditable; 
    public List<String> comboVals; 

    public MyField(String name, String value, String fieldType, boolean isEditable, List<String> comboVals) { 
     super(); 
     this.name = name; 
     this.value = new SimpleStringProperty(value); 
     this.fieldType = fieldType; 
     this.isEditable = isEditable; 
     this.comboVals = comboVals; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getValue() { 
     return value.get(); 
    } 
    public StringProperty valueProperty() { 
     return value; 
    } 

    public void setValue(String value) { 
     this.value.set(value); 
    } 

    public String getFieldType() { 
     return fieldType; 
    } 

    public void setFieldType(String fieldType) { 
     this.fieldType = fieldType; 
    } 

    public List<String> getComboVals() { 
     return comboVals; 
    } 

    public void setComboVals(List<String> comboVals) { 
     this.comboVals = comboVals; 
    } 

    public boolean isEditable() { 
     return isEditable; 
    } 

    public void setEditable(boolean isEditable) { 
     this.isEditable = isEditable; 
    } 

} 

public class MyFieldCellFactory 
     implements Callback<TreeTableColumn<MyField, String>, TreeTableCell<MyField, String>> { 

    @Override 
    public TreeTableCell<MyField, String> call(TreeTableColumn<MyField, String> param) { 
     return new MyFieldCell(); 
    } 

} 

public class MyFieldCell extends TreeTableCell<MyField, String> { 
    private MyEditingControlProvider controlProvider = new MyCellEditingControlProvider(); 

    public MyFieldCell() { 
     super(); 
    } 

    @Override 
    public void updateItem(String item, boolean empty) { 
     super.updateItem(item, empty); 
     if (empty) { 
      setText(null); 
      setGraphic(null); 
     } else { 
      setText(null); 
      System.out.println("updating getItem()" + getItem()); 
      System.out.println("getTableRow().getItem().getName() " + getTreeTableRow().getItem().getName()); 
      setGraphic(controlProvider.getControl(getTreeTableRow().getItem())); 
     } 
    } 

    protected void commitEdit() { 
     super.commitEdit(getItem()); 
     System.out.println("committing edit"); 
     MyField myField = getTreeTableRow().getItem(); 
     controlProvider.updateFromControl(myField); 
    } 
} 

public interface MyEditingControlProvider { 
    public Control getControl(MyField field); 
    public void updateFromControl(MyField field); 
} 

public class MyCellEditingControlProvider implements MyEditingControlProvider { 

    private Map<String, MyEditingControlProvider> providers; 

    public MyCellEditingControlProvider() { 
     providers = new HashMap<>(); 
     providers.put("check", new CheckProvider()); 
     providers.put("combo", new ComboProvider()); 
     providers.put("text", new TextProvider()); 
    } 

    @Override 
    public Control getControl(MyField field) { 
     if (field == null || field.getFieldType() == null) { 
      return null; 
     } else { 
      return providers.get(field.getFieldType()).getControl(field); 
     } 
    } 

    @Override 
    public void updateFromControl(MyField field) { 
     providers.get(field.getFieldType()).updateFromControl(field); 
    } 

} 

public class CheckProvider implements MyEditingControlProvider { 
    private CheckBox checkBox; 


    @Override 
    public Control getControl(MyField field) { 
     if (checkBox == null) { 
      createCheckBox(field); 
     } 
     return checkBox; 
    } 

    private void createCheckBox(MyField field) { 
     checkBox = new CheckBox("Check"); 
     checkBox.setSelected(getBoolean(field)); 
     field.valueProperty().bindBidirectional(checkBox.selectedProperty(), new BooleanStringConverter()); 
     checkBox.focusedProperty().addListener(new ChangeListener<Boolean>() { 
      @Override 
      public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 
       if (!newValue) { 
        updateFromControl(field); 
       } 
      } 
     }); 
    } 

    private Boolean getBoolean(MyField field) { 
     return field.getValue() == null ? false : convertYNToBoolean(field.getValue()); 
    } 

    private Boolean convertYNToBoolean(String val) { 
     if (val != null && val.equals("Y")) { 
      return true; 
     } else { 
      return false; 
     } 
    } 

    private String convertBooleanToYN(Boolean val) { 
     if (val) { 
      return "Y"; 
     } else { 
      return "N"; 
     } 
    } 

    @Override 
    public void updateFromControl(MyField field) { 
     field.setValue(convertBooleanToYN(checkBox.isSelected())); 
    } 

} 

public class ComboProvider implements MyEditingControlProvider { 
    private ComboBox<String> comboBox; 

    @Override 
    public Control getControl(MyField field) { 
     if (comboBox == null) { 
      createComboBox(field); 
     } 
     return comboBox; 
    } 

    private void createComboBox(MyField field) { 
     comboBox = new ComboBox<String>(); 
     comboBox.setEditable(true); 
     resetBox(field); 
     field.valueProperty().bindBidirectional(comboBox.valueProperty()); 

    } 

    private void resetBox(MyField field) { 
     comboBox.getItems().clear(); 
     comboBox.getItems().addAll(field.getComboVals()); 
    } 

    @Override 
    public void updateFromControl(MyField field) { 
     field.setValue(comboBox.getValue()); 
    } 

} 

public class TextProvider implements MyEditingControlProvider { 
    private TextField textField; 

    @Override 
    public Control getControl(MyField field) { 
     if (textField == null) { 
      createTextField(field); 
     } 
     return textField; 
    } 

    private void createTextField(MyField field) { 
     textField = new TextField(field.getValue()); 
     field.valueProperty().bindBidirectional(textField.textProperty()); 
    } 

    @Override 
    public void updateFromControl(MyField field) { 
     field.setValue(textField.getText()); 
    } 

} 

} 

答えて

2

私はあなたが管理プロバイダに至るまでのセルを渡す必要が推測:

public interface MyEditingControlProvider { 
    public Control getControl(TreeTableCell<MyField, String> cell); 
    public void updateFromControl(MyField field); 
} 

public class MyCellEditingControlProvider implements MyEditingControlProvider { 

    private Map<String, MyEditingControlProvider> providers; 

    public MyCellEditingControlProvider() { 
     providers = new HashMap<>(); 
     providers.put("check", new CheckProvider()); 
     providers.put("combo", new ComboProvider()); 
     providers.put("text", new TextProvider()); 
    } 

    @Override 
    public Control getControl(TreeTableCell<MyField, String> cell) { 
     if (field == null || field.getFieldType() == null) { 
      return null; 
     } else { 
      return providers.get(field.getFieldType()).getControl(cell); 
     } 
    } 

    @Override 
    public void updateFromControl(MyField field) { 
     providers.get(field.getFieldType()).updateFromControl(field); 
    } 

} 

その後、個々の実装を行うことができ、例えば

public class CheckProvider implements MyEditingControlProvider { 
    private CheckBox checkBox; 


    @Override 
    public Control getControl(TreeTableCell<MyField, String> cell) { 
     if (checkBox == null) { 
      createCheckBox(cell); 
     } 
     return checkBox; 
    } 

    private void createCheckBox(TreeTableCell<MyField, String> cell) { 
     checkBox = new CheckBox("Check"); 
     MyField field = cell.getTreeTableRow().getItem(); 
     checkBox.setSelected(getBoolean(field)); 
     field.valueProperty().bindBidirectional(checkBox.selectedProperty(), new BooleanStringConverter()); 
     checkBox.setOnAction(cell.commitEdit(convertBooleanToYN(checkBox.isSelected()))); 
    } 

    // ... 

} 
関連する問題