2017-11-22 1 views
2

조직의 월별 월급을 포함하는 javafx 테이블이 있습니다. 이 표에서 기본 금액으로 일부 금액을 표시하여 사용자가 금액을 업데이트하거나 다른 방법으로 진행할 수 있도록합니다. 실제로 필요한 것은 사용자가 모든 값을 업데이트하면 테이블 observablelist에 즉시 바인드해야합니다.Javafx 테이블 뷰 바인딩이 cellValueFactory 내부에서 테이블 observablelist로 변경됩니다.

만들기 테이블 :

private void initCollectionTable(ObservableList<Member> mList) { 

    ... 

    total_pay_col.setCellValueFactory(new SubscriptionValueFactory()); 
    detail_view_col.setCellValueFactory(new DisplaySubscriptionFactory()); 

    ... 

    collection_tbl.setItems(mlz); 
} 

SubscriptionValueFactory 등급 :

public class SubscriptionValueFactory implements Callback<TableColumn.CellDataFeatures<Member, String>, ObservableValue<String>> { 

    @Override 
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Member, String> param) { 

     //Here Subscriptions are equal to various member charges 
     Member ml = param.getValue(); 
     List<MemberSubscriptions> mbrSubs = new ArrayList<>(ml.getMemberSubscriptions()); 
     double sum =mbrSubs.stream().mapToDouble(a -> a.getAmount()).sum(); 
     return new SimpleObjectProperty<>(TextFormatHandler.CURRENCY_DECIMAL_FORMAT.format(sum)); 
    } 

} 

DisplaySubscriptionFactory 클래스

public class DisplaySubscriptionFactory implements Callback<TableColumn.CellDataFeatures<Member, Button>, ObservableValue<Button>> { 

    @Override 
    public ObservableValue<Button> call(TableColumn.CellDataFeatures<Member, Button> param) { 
     Member ml = param.getValue(); 

     List<MemberSubscriptions> mbrSubs = new ArrayList<>(ml.getMemberSubscriptions()); 

     double sum =mbrSubs.stream().mapToDouble(a -> a.getAmount()).sum(); 
     boolean flag = // SOME BOOLEAN CHECK HERE----- 

     param.getValue().setTotalSubscription(sum); 
     Button button = new Button("View Info"); 
     button.setOnAction((evt) -> { 
      Alert alert_details = new Alert(Alert.AlertType.INFORMATION); 
      alert_details.setTitle("Subscription Information"); 
      alert_details.setHeaderText("Member Subscription information for each installment"); 
      alert_details.getDialogPane().setContent(createContentGrid(mbrSubs, sum, flag)); 
      alert_details.show(); 
     }); 

     return new SimpleObjectProperty<>(button); 
    } 

이 방법은 텍스트 필드 내에 회원 요금을 표시하는 격자를 만듭니다. 따라서 텍스트 필드 내에서 값이 변경되면 테이블 observablelist의 자체 속성을 업데이트해야합니다.

private Node createContentGrid(List<MemberSubscriptions> mbrSubs, double sum, boolean flag) { 

    GridPane grid = new GridPane(); 
    grid.setHgap(20); 
    grid.setVgap(10); 
    grid.setPadding(new Insets(20, 20, 10, 10)); 

    Label totLabel = new Label(TextFormatHandler.CURRENCY_DECIMAL_FORMAT.format(sum)); 
    totLabel.setFont(Font.font("System Bold", 21.0)); 
    Label col_h_1 = new Label("Subscription"); 
    col_h_1.setFont(Font.font("System Bold", 17.0)); 
    Label col_h_2 = new Label("Amount"); 
    col_h_2.setFont(Font.font("System Bold", 17.0)); 

    grid.add(col_h_1, 0, 0); 
    grid.add(col_h_2, 1, 0); 
    Label[] labels = new Label[mbrSubs.size()]; 
    TextField[] fields = new TextField[mbrSubs.size()]; 
    for (int i = 0; i < mbrSubs.size(); i++) { 
     MemberSubscriptions get = mbrSubs.get(i); 
     labels[i] = new Label("label"); 
     fields[i] = new TextField(); 
     fields[i].setTextFormatter(TextFormatHandler.currencyFormatter()); 
     labels[i].setText(get.getMemberSubscription().getFeeName()); 
     fields[i].setText(TextFormatHandler.CURRENCY_DECIMAL_FORMAT.format(get.getAmount())); 
     grid.add(labels[i], 0, i + 1); 
     grid.add(fields[i], 1, i + 1); 
    } 
    grid.add(totLabel, 1, mbrSubs.size() + 1); 
    return grid; 
} 

회원 등급 :

public class Member { 
    private Integer id; 
    private String memberId; 
    ... 
    private Set<MemberSubscriptions> memberSubscriptions = new HashSet<>(); 
    ... 

MemberSubscriptions 클래스

public class MemberSubscriptions { 
    private Integer id; 
    private Member member; 
    private Double amount; 
    ... 

enter image description here

+0

가능한 경우,'membersSubscriptions'는'ObservableSet'이어야하고'MemberSubscription'의 속성은 JavaFX- 스타일 observables/properties 여야합니다. 또한 왜 'MemberSubscription' 필드가있는'MembersSubscriptions' 클래스가 필요한지 이해하지 못합니다.'MemberSubscription' 필드가 아닌 ...'MemberS'의 세트가 실제 구독이 아니어야합니다. – Itai

+1

첫째,'initCollectionTable()'은'mList'를 전달하지만, 어떻게 든'setItems()'는 아무 데서도 오는'mlz'를 사용합니다.둘째,'setCellValueFactory()'내부에 버튼을 생성해서는 안되며'setCellFactory()'에 있어야합니다. 셋째, 'Member' 및'MemberSubscriptions' 클래스에서 'IntegerProperty'와 같은 속성을 사용해야합니다. 넷째,'FXCollections.observableArrayList (Callback extractor)'로 인스턴스화 된 ObservableList를 사용해야합니다. – Jai

+0

@sillyfly 실수로 죄송합니다 ... MemberSubscriptions 클래스를 업데이트했습니다. –

답변

1

나는 당신의 질문에 대한 답을 발견했다 생각합니다. 나는 그것을 단순화 했으므로 어쩌면 그것을 사용하여 문제를 해결할 수 있습니다.

모델 :

public class Model { 

    private LongProperty id; 
    private DoubleProperty amount; 
    private ObjectProperty<SubModel> subModel; 

    public Model(Long id, Double amount, SubModel subModel) { 
     this.id = new SimpleLongProperty(id); 
     this.amount = new SimpleDoubleProperty(amount); 
     this.subModel = new SimpleObjectProperty<>(subModel); 
    } 

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

    public LongProperty idProperty() { 
     return id; 
    } 

    public DoubleProperty amountProperty() { 
     return amount; 
    } 

    public SubModel getSubModel() { 
     return subModel.get(); 
    } 

    public ObjectProperty<SubModel> subModelProperty() { 
     return subModel; 
    } 
} 

서브 모델 :

public class SubModel { 

    private LongProperty id; 
    private DoubleProperty xAmount; 
    private DoubleProperty yAmount; 

    public SubModel(Long id, Double xAmount, Double yAmount) { 
     this.id = new SimpleLongProperty(id); 
     this.xAmount = new SimpleDoubleProperty(xAmount); 
     this.yAmount = new SimpleDoubleProperty(yAmount); 
    } 

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


    public double getxAmount() { 
     return xAmount.get(); 
    } 

    public DoubleProperty xAmountProperty() { 
     return xAmount; 
    } 

    public double getyAmount() { 
     return yAmount.get(); 
    } 

    public DoubleProperty yAmountProperty() { 
     return yAmount; 
    } 
} 

버튼 셀 :

public class ButtonTableCell<S, T> extends TableCell<S, T> { 

    private Button button; 

    public ButtonTableCell() { 
     this.button = new Button("View Info"); 
     button.setOnAction(event -> { 
      Model model = (Model) getTableRow().getItem(); 
      Dialog<SubModel> dialog = new AmountDialog(model.getSubModel()); 
      dialog.getDialogPane().getButtonTypes().add(ButtonType.OK); 
      dialog.showAndWait().ifPresent(result -> { 
       model.amountProperty().set(result.getxAmount() + result.getyAmount()); 
      }); 
     }); 
    } 

    @Override protected void updateItem(T item, boolean empty) { 
     super.updateItem(item, empty); 
     setText(null); 
     if (empty) { 
      setGraphic(null); 
     } else { 
      setGraphic(button); 
     } 
    } 
} 

대화 :

public class AmountDialog extends Dialog<SubModel> { 

    public AmountDialog(SubModel model) { 
     setTitle("Title"); 
     setHeaderText("Header"); 
     getDialogPane().setContent(createContent(model)); 
     setResultConverter(button -> { 
      if (button == ButtonType.OK) { 
       return model; 
      } 
      return null; 
     }); 
    } 

    private GridPane createContent(SubModel model) { 
     GridPane grid = new GridPane(); 
     grid.setHgap(20); 
     grid.setVgap(10); 
     grid.setPadding(new Insets(20, 20, 10, 10)); 
     Label sub = new Label("Sub"); 
     Label amount = new Label("Amount"); 

     Label amountX = new Label("AmountX"); 
     Label amountY = new Label("AmountY"); 

     TextField tfAmounX = new TextField(String.valueOf(model.getxAmount())); 
     TextField tfAmountY = new TextField(String.valueOf(model.getyAmount())); 

     Bindings.bindBidirectional(tfAmounX.textProperty(), model.xAmountProperty(), new StringDoubleConverter()); 
     Bindings.bindBidirectional(tfAmountY.textProperty(), model.yAmountProperty(), new StringDoubleConverter()); 

     grid.add(sub, 0, 0); 
     grid.add(amount, 1, 0); 

     grid.add(amountX, 0, 1); 
     grid.add(tfAmounX, 1, 1); 

     grid.add(amountY, 0, 2); 
     grid.add(tfAmountY, 1, 2); 

     return grid; 
    } 

    private class StringDoubleConverter extends StringConverter<Number> { 
     @Override public String toString(Number object) { 
      return object.toString(); 
     } 

     @Override public Number fromString(String string) { 
      // You may handle NumberFormatException. 
      return Double.valueOf(string); 
     } 
    } 
} 
다음은 내 수업에 대한 내 코드입니다

그리고 컨트롤러 :

public class Controller implements Initializable { 

    @FXML 
    private TableView<Model> table; 
    @FXML 
    private TableColumn<Model, Long> colId; 
    @FXML 
    private TableColumn<Model, Double> colAmount; 
    @FXML 
    private TableColumn<Model, SubModel> colInfo; 

    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
     setupTable(); 
     setupData(); 
    } 

    private void setupTable() { 
     colId.setCellValueFactory(data -> data.getValue().idProperty().asObject()); 
     colAmount.setCellValueFactory(data -> data.getValue().amountProperty().asObject()); 
     colInfo.setCellValueFactory(data -> data.getValue().subModelProperty()); 

     colInfo.setCellFactory(factory -> new ButtonTableCell<>()); 
    } 

    private void setupData() { 
     SubModel firstSubModel = new SubModel(1L, 0D, 0D); 
     SubModel secondSubModel = new SubModel(2L, 0D, 0D); 

     Model fist = new Model(1L, 0D, firstSubModel); 
     Model second = new Model(2L, 0D, secondSubModel); 

     ObservableList<Model> tableData = FXCollections.observableArrayList(); 
     tableData.add(fist); 
     tableData.add(second); 

     table.setItems(tableData); 
    } 
} 

나는 조금 긴 답을 알고 있지만, 나는 그것이 문제가 해결되기를 바랍니다. 나에게 그것은 OK 프레스에서 일하고 있지만 대화 상자의 모든 필드에서 값을 변경하면 즉시 업데이트하고 싶을 수도 있습니다.

+0

감사합니다. 그것은 일했다 :) –

관련 문제