2016-02-15 5 views
0

Я использую TableView, который заполнен моей моделью.Как связать управление TableCell с базовой моделью строки в javafx?

Я хочу использовать элемент управления прядильщика в одной колонке.

Я могу создать счетчик в ячейках в нужной колонке, , но я изо всех сил стараюсь привязать значение прядильцев к свойству моделей.

Это FXML

<ScrollPane> 
    <content> 
     <TableView prefHeight="525.0" prefWidth="814.0"> 
     <columns> 
      <TableColumn prefWidth="75.0"> 
      <cellValueFactory><PropertyValueFactory property="state"/></cellValueFactory> 
      </TableColumn> 
      <TableColumn prefWidth="75.0" text="Side"> 
      <cellValueFactory><PropertyValueFactory property="side"/></cellValueFactory> 
      </TableColumn> 
      <TableColumn prefWidth="75.0" text="Source"> 
      <cellValueFactory><PropertyValueFactory property="sourceContract"/></cellValueFactory> 
      </TableColumn> 
      <TableColumn prefWidth="75.0" text="Reference"> 
      <cellValueFactory><PropertyValueFactory property="referenceContract"/></cellValueFactory> 
      </TableColumn> 
      <TableColumn prefWidth="75.0" text="Destination"> 
      <cellValueFactory><PropertyValueFactory property="destinationContract"/></cellValueFactory> 
      </TableColumn> 
      <TableColumn prefWidth="75.0" text="Margin" editable="true"> 
      <cellFactory><SpinnerTableCellFactory /></cellFactory> 
      <cellValueFactory><PropertyValueFactory property="margin"/></cellValueFactory> 
      </TableColumn> 
      <TableColumn prefWidth="75.0" text="Bot"> 
      <cellValueFactory><PropertyValueFactory property="bot"/></cellValueFactory> 
      </TableColumn> 
      <TableColumn prefWidth="75.0" text="Price"> 
      <cellValueFactory><PropertyValueFactory property="price"/></cellValueFactory> 
      </TableColumn> 
      <TableColumn prefWidth="75.0" text="Volume"> 
      <cellValueFactory><PropertyValueFactory property="volume"/></cellValueFactory> 
      </TableColumn> 
     </columns> 
     <items> 
      <FXCollections fx:factory="observableArrayList"> 
      <GridRowModel state="false" side="BID" sourceContract="s01" referenceContract="" destinationContract="d01" margin="0" bot="MinMax" price="15.125" volume="0" /> 
      <GridRowModel state="false" side="ASK" sourceContract="s02" referenceContract="" destinationContract="d02" margin="0" bot="MinMax" price="15.125" volume="0" /> 
      </FXCollections> 
     </items> 
     </TableView> 
    </content> 
</ScrollPane> 

И это SpinnerTableCellFactory

public class SpinnerTableCellFactory<S, T> implements Callback<TableColumn<S, Double>, TableCell<S, Double>> { 

    @Override 
    public TableCell<S, Double> call(TableColumn<S, Double> param) { 

    return new TableCell<S, Double>() { 

     Spinner<Double> spinner = new Spinner<>(0d, 1d, 0d, 0.025d); 

     protected void updateItem(Double item, boolean empty) { 
     super.updateItem(item, empty); 

     if (empty) { 
      setText(null); 
      setGraphic(null); 
     } else { 
      if (isEditing()) { 
      setText(null); 
      setGraphic(null); 
      } else { 
      spinner.getValueFactory().setValue(getItem()); 
      setText(null); 
      setGraphic(spinner); 
      } 
     } 
     }; 
    }; 
    } 
} 

Когда FXML загружен в updateItem метод вызывается со значениями по умолчанию из FXML для margin собственности. Я вижу и использую счетчик в ячейках. Но как передать новое значение счетчика обратно в свойство margin в объекте GridRowModel?

ответ

1

Просто зарегистрировать слушатель с Прядильщиками valueProperty():

public class SpinnerTableCellFactory<S, T> implements Callback<TableColumn<S, Double>, TableCell<S, Double>> { 

    @Override 
    public TableCell<S, Double> call(TableColumn<S, Double> param) { 

    return new TableCell<S, Double>() { 

     Spinner<Double> spinner = new Spinner<>(0d, 1d, 0d, 0.025d); 

     { 
      spinner.valueProperty().addListener((obs, oldValue, newValue) -> { 
       ObservableValue<Double> value = getTableColumn().getCellObservableValue(getIndex()); 
       if (value instanceof WritableValue) { 
        ((WritableValue<Double>)value).setValue(newValue); 
       } 
      }); 
     } 

     protected void updateItem(Double item, boolean empty) { 
     super.updateItem(item, empty); 

     if (empty) { 
      setText(null); 
      setGraphic(null); 
     } else { 
      if (isEditing()) { 
      setText(null); 
      setGraphic(null); 
      } else { 
      spinner.getValueFactory().setValue(getItem()); 
      setText(null); 
      setGraphic(spinner); 
      } 
     } 
     }; 
    }; 
    } 
} 

Я предполагаю, что здесь, что ваша модель класс GridRowModel следует JavaFX properties pattern.

Если вы не используете JavaFX Properties, или хотите, чтобы избежать броска, вы можете дать мобильный заводу BiConsumer<GridRowModel, Double> обрабатывать обновление:

public class SpinnerTableCellFactory<S, T> implements Callback<TableColumn<S, Double>, TableCell<S, Double>> { 

    private BiConsumer<S, Double> updater = null ; 

    public void setUpdater(BiConsumer<S, Double> updater) { 
     this.updater = updater ; 
    } 

    @Override 
    public TableCell<S, Double> call(TableColumn<S, Double> param) { 

    return new TableCell<S, Double>() { 

     Spinner<Double> spinner = new Spinner<>(0d, 1d, 0d, 0.025d); 

     { 
      spinner.valueProperty().addListener((obs, oldValue, newValue) -> { 
       if (updater != null) { 
        updater.accept(getTableView().getItems().get(getIndex()), newValue); 
       } 
      }); 
     } 

     protected void updateItem(Double item, boolean empty) { 
     super.updateItem(item, empty); 

     if (empty) { 
      setText(null); 
      setGraphic(null); 
     } else { 
      if (isEditing()) { 
      setText(null); 
      setGraphic(null); 
      } else { 
      spinner.getValueFactory().setValue(getItem()); 
      setText(null); 
      setGraphic(spinner); 
      } 
     } 
     }; 
    }; 
    } 
} 

Затем вы можете добавить fx:id к вашей фабрике:

<cellFactory><SpinnerTableCellFactory fx:id="marginCellFactory" /></cellFactory> 

и в контроллере сделать:

@FXML 
private SpinnerTableCellFactory<GridRowModel, Double> marginCellFactory ; 

public void initialize() { 
    marginCellFactory.setUpdater(GridRowModel::setMargin); 
} 
Смежные вопросы