2017-10-16 17 views
0

私の目標は、クラスのインスタンスのすべてのフィールドをtableViewに表示することです。クラスには、String型のフィールドを持つenum型のフィールドがあります。 列挙型は、文字列フィールド名としてComboBoxに表示されます。 もちろん編集可能でなければなりません。JavaFX表示列挙型の文字列(コンボボックスの文字列)(表形式)

今のところうまくいきません: EnumクラスのStringフィールドは、ComboBoxがクリックされた場合にのみ表示され、それ以外の場合は列挙定数の名前です。また、コンボボックスの別の列挙型が選択されている場合、編集のためにコミットすることはできません。 returnをクリックしても、commitEditのどちらのメソッドも呼び出されず、Comboboxの選択も解除されません。編集のために他の列が選択された場合、試行された編集は取り消されます。

私はこれを理解しようと努力しましたので、私はここで私を助けてくれるかもしれないと考えました。 元のタスクはエンタープライズソフトウェアのより大きなクラスであるため、私はこの質問をするために抽象化しました。

String型の列挙型を保持する列を作成し、MyEnum.values()およびMyEnum.valueOf()で機能させることができますが、元のクラスもパフォーマンスが悪いため、大きい。

ここで私のコードを例に挙げます。問題を理解できない場合は、コンボボックスを一度使用してみてください。

テーブルビューのタイプであるクラス:

public class MyClass { 

private MyEnum myEnum; 

private String string; 

public MyClass(MyEnum myEnum, String string) { 
    this.myEnum = myEnum; 
    this.string = string; 
} 

public MyEnum getMyEnum() { 
    return myEnum; 
} 

public void setMyEnum(MyEnum myEnum) { 
    this.myEnum = myEnum; 
} 

public String getString() { 
    return string; 
} 

} 

それは列挙型のフィールドです:

public enum MyEnum { 

EnumOne("First Enum"), 
EnumTwo("Second Enum"); 

private String name; 

public String getName() { 
    return name; 
} 

private MyEnum(String name) { 
    this.name = name; 
} 

} 

FXアプリケーション:

public class NewFXMain extends Application { 

@Override 
public void start(Stage primaryStage) { 
    ObservableList<MyClass> items = FXCollections.observableArrayList(); 
    items.add(new MyClass(MyEnum.EnumOne, "String")); 
    TableView<MyClass> table = new TableView(items); 
    table.setEditable(true); 
    TableColumn<MyClass, MyEnum> myEnumColumn = new TableColumn(); 
    TableColumn<MyClass, String> stringColumn = new TableColumn(); 

    stringColumn.setCellFactory(TextFieldTableCell.forTableColumn()); 
    stringColumn.setCellValueFactory(data -> new ReadOnlyStringWrapper(data.getValue().getString())); 



    myEnumColumn.setCellFactory((param) -> new MyEnumComboBoxCell()); 
    myEnumColumn.setCellValueFactory(data -> new ReadOnlyObjectWrapper(data.getValue().getMyEnum())); 
    myEnumColumn.setOnEditCommit(
      event -> { 
       event.getRowValue().setMyEnum(event.getNewValue()); 
       System.out.println(event.getRowValue().getMyEnum()); 

      }); 

    table.getColumns().addAll(myEnumColumn, stringColumn); 

    StackPane root = new StackPane(); 
    root.getChildren().add(table); 
    Scene scene = new Scene(root, 300, 250); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 

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

} 

class MyEnumComboBoxCell extends ComboBoxTableCell<MyClass, MyEnum> { 

private ComboBox<MyEnum> box; 

public MyEnumComboBoxCell() { 
    box = new ComboBox<>(FXCollections.observableArrayList(MyEnum.values())); 
    box.setCellFactory(new Callback<ListView<MyEnum>, ListCell<MyEnum>>() { 
     @Override 
     public ListCell<MyEnum> call(ListView<MyEnum> param) { 
      return new ListCell<MyEnum>() { 
       @Override 
       protected void updateItem(MyEnum item, boolean empty) { 
        super.updateItem(item, empty); 
        if (item != null) setText(item.getName()); 
       } 

      }; 
     } 
    }); 
} 

@Override 
public void startEdit() { 
    super.startEdit(); 
    setGraphic(box); 
} 

@Override 
public void commitEdit(MyEnum newValue) { 
    super.commitEdit(newValue); 
    if (newValue != null) { 
     setText(newValue.getName()); 
     getTableView().getSelectionModel().getSelectedItem().setMyEnum(newValue); 
     box.setValue(newValue); 
    } 
} 

@Override 
public void updateItem(MyEnum item, boolean empty) { 
    super.updateItem(item, empty); 
    if (empty) { 
     setGraphic(null); 
    } else { 
     setGraphic(null); 
     setText(item.getName()); 
    } 
} 

} 

答えて

1

代わりupdateItem使用中のようなStringConverterの名前を設定します:

0123セルのコンストラクタで
public class MyEnumConverter extends StringConverter<MyEnum>{ 

    @Override public String toString(MyEnum enumConstant) { 
     return enumConstant.getName(); 
    } 

    @Override public MyEnum fromString(String string) { 
     return MyEnum.valueOf(string); 
    } 
} 

その後:

this.setConverter(new MyEnumConverter()); 

編集:あなたはありません@OverrideComboBoxTableCellの方法の全て、それらのすべては、あなたが望むように働いているからです。一方、テーブルセルには独自のComboBoxを指定しないでください。 StringConverterを追加して項目を設定するだけです。あなたは、私が先に述べたように、あなたがStringConverterのために別のクラスを作成することができます好む場合は、単に

myEnumColumn.setCellFactory((param) -> new ComboBoxTableCell<>(new StringConverter<MyEnum>() { 
      @Override public String toString(MyEnum object) { 
       return object.getName(); 
      } 

      @Override public MyEnum fromString(String string) { 
       return MyEnum.valueOf(string); 
      } 
     }, MyEnum.values())); 

myEnumColumn.setCellFactory(factory -> new ComboBoxTableCell<>(new MyEnumConverter(), MyEnum.values())); 

あなたも取り除くことができます

あなたはこのように使用することができますmyEnumColumn.setOnEditCommit

+0

私はあなたのソリューションを実装しようとしましたが、少し違っていてもまだ機能していません。実際に私の例を書き直してもうまくいきましたか? 私はそれ以前に自分自身を試みたので、おそらくそうではないと思いますか? –

+0

私はあなたのコード内の別の問題を発見したので、私はうん、あなたはバッキングモデルの値を設定するには、このソリューションを使用することができます – Sunflame

0

ありがとうございます!実際に私はこれを部分的に別の人と一緒に過ごしたので、これは本当に感謝しています! :)

しかし、 私はsetOnEditCommitを実装する必要があります。それ以外の場合は、tableColumnをバッキングするmyEnumフィールドは変更されません。これで全てが機能します。なしでは、表示されるものだけが変更されます。

myEnumColumn.setOnEditCommit(
      event -> 
    { 
     event.getRowValue().setMyEnum(event.getNewValue()); 

    }); 
+0

\]。答えを編集してきましたが、その希望モデルクラスを作成することによって、これを行うために多くのエレガントな方法があります1つの行の情報を保持すると、手動による介入なしにすべてが発生します。 – Sunflame