Как работать с JavaFx TableView с пользовательской ячейкой таблицы, используя редактируемые ячейки Combobox

Я хотел бы создать таблицу со следующими функциями

  • Редактировать при нажатии клавиши
  • Клавиша ввода = следующая строка
  • Клавиша Tab = следующий столбец
  • Клавиша Escape = Отменить редактирование

Окно выглядит следующим образом

Основная проблема, которая возникает, когда мы фокусируемся на поле со списком, фокус перемещается за пределы таблицы. Мне нужно решение, при котором фокус остается в таблице или на следующей ячейке таблицы и фиксирует выбранное значение поля со списком. Поле со списком имеет тип Item.

      ComboBox<Item> items = new ComboBox<>();

Таблица выглядит следующим образом

      public TableView<Purchase> _purchase_table;
public TableColumn<Purchase, String> _id;
public TableColumn<Purchase, Item> _name_of_item; //Of Type Purchase,Item
public TableColumn<Purchase, String> _quantity;
public TableColumn<Purchase, String> _rate;
public TableColumn<Purchase, String> _per;
public TableColumn<Purchase, String> _amount;

Класс покупки выглядит следующим образом

      public class Purchase {
private SimpleStringProperty serialNumber;
private SimpleObjectProperty<Item> itemName;
private SimpleStringProperty quantity;
private SimpleStringProperty rate;
private SimpleStringProperty per;
private SimpleStringProperty amount;

public Purchase() {
    serialNumber = new SimpleStringProperty();
    itemName = new SimpleObjectProperty<>();
    quantity = new SimpleStringProperty();
    rate = new SimpleStringProperty();
    per = new SimpleStringProperty();
    amount = new SimpleStringProperty();
}

public String getSerialNumber() {
    return serialNumber.get();
}

public SimpleStringProperty serialNumberProperty() {
    return serialNumber;
}

public void setSerialNumber(String serialNumber) {
    this.serialNumber.set(serialNumber);
}

public Item getItemName() {
    return itemName.get();
}

public SimpleObjectProperty<Item> itemNameProperty() {
    return itemName;
}



public void setItemName(Item itemName) {
    this.itemName.set(itemName);
}

public String getQuantity() {
    return quantity.get();
}

public SimpleStringProperty quantityProperty() {
    return quantity;
}

public void setQuantity(String quantity) {
    this.quantity.set(quantity);
}

public String getRate() {
    return rate.get();
}

public SimpleStringProperty rateProperty() {
    return rate;
}

public void setRate(String rate) {
    this.rate.set(rate);
}

public String getPer() {
    return per.get();
}

public SimpleStringProperty perProperty() {
    return per;
}

public void setPer(String per) {
    this.per.set(per);
}

public String getAmount() {
    return amount.get();
}

public SimpleStringProperty amountProperty() {
    return amount;
}

public void setAmount(String amount) {
    this.amount.set(amount);
}
}

Класс Item выглядит следующим образом

      public class Item {
private SimpleStringProperty id;
private SimpleStringProperty itemName;
private SimpleStringProperty stockGroupID;
private SimpleStringProperty stockGroup;
private SimpleStringProperty unitID;
private SimpleStringProperty unitName;
private SimpleStringProperty taxabilityID;
private SimpleStringProperty taxability;
private SimpleStringProperty hsn;
private SimpleStringProperty itemDescription;
private SimpleStringProperty integratedTax;
private SimpleStringProperty centralTax;
private SimpleStringProperty stateTax;
private SimpleStringProperty cess;

public Item() {
    id = new SimpleStringProperty();
    itemName = new SimpleStringProperty();
    stockGroupID = new SimpleStringProperty();
    stockGroup = new SimpleStringProperty();
    unitID = new SimpleStringProperty();
    unitName = new SimpleStringProperty();
    taxabilityID = new SimpleStringProperty();
    taxability = new SimpleStringProperty();
    hsn = new SimpleStringProperty();
    itemDescription = new SimpleStringProperty();
    integratedTax = new SimpleStringProperty();
    centralTax = new SimpleStringProperty();
    stateTax = new SimpleStringProperty();
    cess = new SimpleStringProperty();
}
public Item(String id,String itemName,String stockGroupID,String stockGroup,String unitID,String unitName,String taxabilityID,
            String taxability,String hsn,String itemDescription,String integratedTax,String centralTax,
            String stateTax,String cess) {
    this.id = new SimpleStringProperty(id);
    this.itemName = new SimpleStringProperty(itemName);
    this.stockGroupID = new SimpleStringProperty(stockGroupID);
    this.stockGroup = new SimpleStringProperty(stockGroup);
    this.unitID = new SimpleStringProperty(unitID);
    this.unitName = new SimpleStringProperty(unitName);
    this.taxabilityID = new SimpleStringProperty(taxabilityID);
    this.taxability = new SimpleStringProperty(taxability);
    this.hsn = new SimpleStringProperty(hsn);
    this.itemDescription = new SimpleStringProperty(itemDescription);
    this.integratedTax = new SimpleStringProperty(integratedTax);
    this.centralTax = new SimpleStringProperty(centralTax);
    this.stateTax = new SimpleStringProperty(stateTax);
    this.cess = new SimpleStringProperty(cess);
}

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

public SimpleStringProperty idProperty() {
    return id;
}

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

public String getItemName() {
    return itemName.get();
}

public SimpleStringProperty itemNameProperty() {
    return itemName;
}

public void setItemName(String itemName) {
    this.itemName.set(itemName);
}

public String getStockGroupID() {
    return stockGroupID.get();
}

public SimpleStringProperty stockGroupIDProperty() {
    return stockGroupID;
}

public void setStockGroupID(String stockGroupID) {
    this.stockGroupID.set(stockGroupID);
}

public String getStockGroup() {
    return stockGroup.get();
}

public SimpleStringProperty stockGroupProperty() {
    return stockGroup;
}

public void setStockGroup(String stockGroup) {
    this.stockGroup.set(stockGroup);
}

public String getUnitID() {
    return unitID.get();
}

public SimpleStringProperty unitIDProperty() {
    return unitID;
}

public void setUnitID(String unitID) {
    this.unitID.set(unitID);
}

public String getUnitName() {
    return unitName.get();
}

public SimpleStringProperty unitNameProperty() {
    return unitName;
}

public void setUnitName(String unitName) {
    this.unitName.set(unitName);
}

public String getTaxabilityID() {
    return taxabilityID.get();
}

public SimpleStringProperty taxabilityIDProperty() {
    return taxabilityID;
}

public void setTaxabilityID(String taxabilityID) {
    this.taxabilityID.set(taxabilityID);
}

public String getTaxability() {
    return taxability.get();
}

public SimpleStringProperty taxabilityProperty() {
    return taxability;
}

public void setTaxability(String taxability) {
    this.taxability.set(taxability);
}

public String getHsn() {
    return hsn.get();
}

public SimpleStringProperty hsnProperty() {
    return hsn;
}

public void setHsn(String hsn) {
    this.hsn.set(hsn);
}

public String getItemDescription() {
    return itemDescription.get();
}

public SimpleStringProperty itemDescriptionProperty() {
    return itemDescription;
}

public void setItemDescription(String itemDescription) {
    this.itemDescription.set(itemDescription);
}

public String getIntegratedTax() {
    return integratedTax.get();
}

public SimpleStringProperty integratedTaxProperty() {
    return integratedTax;
}

public void setIntegratedTax(String integratedTax) {
    this.integratedTax.set(integratedTax);
}

public String getCentralTax() {
    return centralTax.get();
}

public SimpleStringProperty centralTaxProperty() {
    return centralTax;
}

public void setCentralTax(String centralTax) {
    this.centralTax.set(centralTax);
}

public String getStateTax() {
    return stateTax.get();
}

public SimpleStringProperty stateTaxProperty() {
    return stateTax;
}

public void setStateTax(String stateTax) {
    this.stateTax.set(stateTax);
}

public String getCess() {
    return cess.get();
}

public SimpleStringProperty cessProperty() {
    return cess;
}

public void setCess(String cess) {
    this.cess.set(cess);
}
}

Класс модели покупки

      public class PurchaseModel {
private ObservableList<Purchase> purchases;
private ObservableList<Item> items;
private int row,column;
public PurchaseModel() {
    row = 0;
    column = 0;
    purchases = FXCollections.observableArrayList();
    Purchase purchase = new Purchase();
    purchase.setSerialNumber("1");
    purchase.setItemName(getItem());
    purchase.setQuantity("4");
    purchase.setRate("20.00");
    purchase.setPer("Pcs");
    purchase.setAmount("80.00");
    purchases.add(purchase);

    items = FXCollections.observableArrayList();
    Item item = new Item();
    item.setId("1");
    item.setItemName("Lux");
    item.setStockGroupID("1");
    item.setStockGroup("items @ 5%");
    item.setUnitID("1");
    item.setUnitName("Kg");
    item.setTaxabilityID("1");
    item.setTaxability("5%");
    item.setHsn("344344");
    item.setItemDescription("dkfmks skmd");
    item.setIntegratedTax("5");
    item.setCentralTax("2.5");
    item.setStateTax("2.5");
    item.setCess("0.0");
    items.add(item);

    item = new Item();
    item.setId("2");
    item.setItemName("Godrej");
    item.setStockGroupID("1");
    item.setStockGroup("items @ 5%");
    item.setUnitID("1");
    item.setUnitName("Kg");
    item.setTaxabilityID("1");
    item.setTaxability("5%");
    item.setHsn("344344");
    item.setItemDescription("dkfmks skmd");
    item.setIntegratedTax("5");
    item.setCentralTax("2.5");
    item.setStateTax("2.5");
    item.setCess("0.0");
    items.add(item);

    item = new Item();
    item.setId("2");
    item.setItemName("Pears");
    item.setStockGroupID("1");
    item.setStockGroup("items @ 5%");
    item.setUnitID("1");
    item.setUnitName("Kg");
    item.setTaxabilityID("1");
    item.setTaxability("5%");
    item.setHsn("344344");
    item.setItemDescription("dkfmks skmd");
    item.setIntegratedTax("5");
    item.setCentralTax("2.5");
    item.setStateTax("2.5");
    item.setCess("0.0");
    items.add(item);
}

public ObservableList<Purchase> fillPurchaseTableViewWithData(){
    return purchases;
}

public ObservableList<Item> fillItemListViewWithData(){
    return items;
}

public Item getItem(){
    return new Item("1","Porter and Gamble","1","Item @ 5%","1","Kg",
            "1","5%","23323","a very good toy","5","2.5",
            "2.5","0");
}

public int getRow() {
    return row;
}

public void setRow(int row) {
    this.row = row;
}

public int getColumn() {
    return column;
}

public void setColumn(int column) {
    this.column = column;
}
}

Класс контроллера выглядит следующим образом

      public class PurchaseController implements Initializable {

public TableView<Purchase> _purchase_table;
public TableColumn<Purchase, String> _id;
public TableColumn<Purchase, Item> _name_of_item;
public TableColumn<Purchase, String> _quantity;
public TableColumn<Purchase, String> _rate;
public TableColumn<Purchase, String> _per;
public TableColumn<Purchase, String> _amount;

private PurchaseModel theModel;

@Override
public void initialize(URL location, ResourceBundle resources) {

    theModel = new PurchaseModel();

    _id.setCellValueFactory(new IDCellValueFactory());
    _name_of_item.setCellValueFactory(new ItemCellValueFactory());
    _quantity.setCellValueFactory(new QuantityCellValueFactory());
    _rate.setCellValueFactory(new RateCellValueFactory());
    _per.setCellValueFactory(new PerCellValueFactory());
    _amount.setCellValueFactory(new AmountCellValueFactory());

    _name_of_item.setCellFactory(new ItemComboBoxEditingCellFactory());
    //_name_of_item.setOnEditCommit(new ItemCellOnEditCommit() );

    _purchase_table.setItems(theModel.fillPurchaseTableViewWithData());
    _purchase_table.setEditable(true);
    _purchase_table.getSelectionModel().cellSelectionEnabledProperty().set(true);

    _purchase_table.getFocusModel().focusedCellProperty().addListener(new PurchaseTableCellSelectionListener());

}

private class IDCellValueFactory implements Callback<TableColumn.CellDataFeatures<Purchase, String>, ObservableValue<String>> {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Purchase, String> param) {
        return param.getValue().serialNumberProperty();
    }
}

private class ItemCellValueFactory implements Callback<TableColumn.CellDataFeatures<Purchase, Item>, ObservableValue<Item>> {
    @Override
    public ObservableValue<Item> call(TableColumn.CellDataFeatures<Purchase, Item> param) {
        return param.getValue().itemNameProperty();
    }
}

private class QuantityCellValueFactory implements Callback<TableColumn.CellDataFeatures<Purchase, String>, ObservableValue<String>> {

    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Purchase, String> param) {
        return param.getValue().quantityProperty();
    }
}

private class RateCellValueFactory implements Callback<TableColumn.CellDataFeatures<Purchase, String>, ObservableValue<String>> {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Purchase, String> param) {
        return param.getValue().rateProperty();
    }
}

private class PerCellValueFactory implements Callback<TableColumn.CellDataFeatures<Purchase, String>, ObservableValue<String>> {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Purchase, String> param) {
        return param.getValue().perProperty();
    }
}

private class AmountCellValueFactory implements Callback<TableColumn.CellDataFeatures<Purchase, String>, ObservableValue<String>> {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Purchase, String> param) {
        return param.getValue().amountProperty();
    }
}

private class  ItemComboBoxEditingCellFactory implements Callback<TableColumn<Purchase, Item>, TableCell<Purchase, Item>> {
    @Override
    public TableCell<Purchase, Item> call(TableColumn<Purchase, Item> param) {
        return new ItemComboBoxEditingCell();
    }
}

private class ItemComboBoxEditingCell extends TableCell<Purchase, Item> {
    private ComboBox<Item> comboBox;
    private TablePosition<Purchase,Item> pos;

    public ItemComboBoxEditingCell() {
        pos = new TablePosition<>(getTableView(),0,null);
    }

    @Override
    public void startEdit() {
        if (!isEmpty()) {
            super.startEdit();
            createComboBox();
            setText(null);
            setGraphic(comboBox);
        }
    }

    @Override
    public void commitEdit(Item newValue) {
        super.commitEdit(newValue);
        ((Purchase)getTableView().getItems()
                .get(getIndex()))
                .setItemName(newValue);

    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        setText(getItemSelected().getItemName());
        setGraphic(null);
    }

    @Override
    protected void updateItem(Item item, boolean empty) {
        super.updateItem(item, empty);

        if (empty){
            setGraphic(null);
            setText(null);

        }else {
            setText(getItemSelected().getItemName());
            setGraphic(comboBox);
        }
    }



    private Item getItemSelected() {
        return getItem() == null ? theModel.getItem() : getItem();
    }

    private void createComboBox() {
        comboBox = new ComboBox<>();
        comboBox.setItems(theModel.fillItemListViewWithData());
        comboBox.setEditable(true);
        comboBox.setCellFactory(new ItemComboBoxCellFactory());
        //comboBox.setOnAction(new ItemComboBoxSelectionListener());
        //comboBox.focusedProperty().addListener(new ItemComboBoxFocusListener());
        //comboBox.showingProperty().addListener(new ItemComboBoxShowingListener());
        comboBox.valueProperty().set(getItemSelected());
        comboBox.setConverter(new ItemComboBoxStringConverter());
        comboBox.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
    }

    private class ItemComboBoxCellFactory implements Callback<ListView<Item>,ListCell<Item>>{
        @Override
        public ListCell<Item> call(ListView<Item> param) {
            return new ItemComboBoxCell();
        }
    }

    private class ItemComboBoxCell extends ListCell<Item>{
        @Override
        protected void updateItem(Item item, boolean empty) {
            super.updateItem(item, empty);
            if (item == null || empty){
                setText(null);
            }else {
                setText(item.getItemName());
            }
        }
    }

    private class ItemComboBoxStringConverter extends StringConverter<Item>{
        private Item i;
        @Override
        public String toString(Item item) {
            if (item == null)
                return null;
            i = item;
            return item.getItemName();
        }

        @Override
        public Item fromString(String s) {
            return i;
        }
    }


}

private class PurchaseTableCellSelectionListener implements ChangeListener<TablePosition>{
    @Override
    public void changed(ObservableValue<? extends TablePosition> observableValue, TablePosition tablePosition, TablePosition t1) {
        int row = t1.getRow();
        int column = t1.getColumn();
        theModel.setRow(row);
        theModel.setColumn(column);
    }
}

Подскажите, пожалуйста, как реализовать все четыре пункта, которые я упомянул выше.

0 ответов

Другие вопросы по тегам