Skip to content

Instantly share code, notes, and snippets.

@haisi
Last active May 20, 2023 19:20
Show Gist options
  • Star 28 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save haisi/0a82e17daf586c9bab52 to your computer and use it in GitHub Desktop.
Save haisi/0a82e17daf586c9bab52 to your computer and use it in GitHub Desktop.
Editable JavaFX TableView with textfield, datepicker and dropdown menu
/*
* Just copy and paste the code.
*/
package editabletableview;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Date;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.DatePicker;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Callback;
/**
*
* @author Hasan Selman Kara
*/
public class Main extends Application {
private TableView<Person> table = new TableView<>();
private final ObservableList<Typ> typData
= FXCollections.observableArrayList(
new Typ("Hund"),
new Typ("Fuchs"),
new Typ("Esel"));
private final ObservableList<Person> data
= FXCollections.observableArrayList(
new Person("Jacob", typData.get(0), new Date()),
new Person("Urs", typData.get(1), new Date()),
new Person("Hans", typData.get(2), new Date()),
new Person("Ueli", typData.get(2), new Date()));
final HBox hb = new HBox();
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setWidth(550);
stage.setHeight(550);
final Label label = new Label("Address Book");
label.setFont(new Font("Arial", 20));
table.setEditable(true);
Callback<TableColumn<Person, String>, TableCell<Person, String>> cellFactory
= (TableColumn<Person, String> param) -> new EditingCell();
Callback<TableColumn<Person, Date>, TableCell<Person, Date>> dateCellFactory
= (TableColumn<Person, Date> param) -> new DateEditingCell();
Callback<TableColumn<Person, Typ>, TableCell<Person, Typ>> comboBoxCellFactory
= (TableColumn<Person, Typ> param) -> new ComboBoxEditingCell();
TableColumn<Person, String> firstNameCol = new TableColumn("Vorname");
firstNameCol.setMinWidth(100);
firstNameCol.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
firstNameCol.setCellFactory(cellFactory);
firstNameCol.setOnEditCommit(
(TableColumn.CellEditEvent<Person, String> t) -> {
((Person) t.getTableView().getItems()
.get(t.getTablePosition().getRow()))
.setFirstName(t.getNewValue());
});
TableColumn<Person, Typ> lastNameCol = new TableColumn("Lieblings Tier");
lastNameCol.setMinWidth(100);
lastNameCol.setCellValueFactory(cellData -> cellData.getValue().typObjProperty());
lastNameCol.setCellFactory(comboBoxCellFactory);
lastNameCol.setOnEditCommit(
(TableColumn.CellEditEvent<Person, Typ> t) -> {
((Person) t.getTableView().getItems()
.get(t.getTablePosition().getRow()))
.setTypObj(t.getNewValue());
});
TableColumn<Person, Date> emailCol = new TableColumn("Geburtstag");
emailCol.setMinWidth(200);
emailCol.setCellValueFactory(cellData -> cellData.getValue().birthdayProperty());
emailCol.setCellFactory(dateCellFactory);
emailCol.setOnEditCommit(
(TableColumn.CellEditEvent<Person, Date> t) -> {
((Person) t.getTableView().getItems()
.get(t.getTablePosition().getRow()))
.setBirthday(t.getNewValue());
});
table.setItems(data);
table.getColumns().addAll(firstNameCol, lastNameCol, emailCol);
final TextField addFirstName = new TextField();
addFirstName.setPromptText("First Name");
addFirstName.setMaxWidth(firstNameCol.getPrefWidth());
final TextField addLastName = new TextField();
addLastName.setPromptText("Last Name");
addLastName.setMaxWidth(lastNameCol.getPrefWidth());
final TextField addEmail = new TextField();
addEmail.setPromptText("email");
addEmail.setMaxWidth(emailCol.getPrefWidth());
final Button addButton = new Button("Add");
addButton.setOnAction((ActionEvent e)
-> {
data.add(new Person(
addFirstName.getText(),
new Typ("Hund"),
new Date()));
addFirstName.clear();
addLastName.clear();
addEmail.clear();
}
);
hb.getChildren().addAll(addFirstName, addLastName, addEmail, addButton);
hb.setSpacing(3);
final VBox vbox = new VBox();
vbox.setSpacing(5);
vbox.setPadding(new Insets(10, 0, 0, 10));
vbox.getChildren().addAll(label, table, hb);
((Group) scene.getRoot()).getChildren().addAll(vbox);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
class EditingCell extends TableCell<Person, String> {
private TextField textField;
private EditingCell() {
}
@Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createTextField();
setText(null);
setGraphic(textField);
textField.selectAll();
}
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText((String) getItem());
setGraphic(null);
}
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(item);
setGraphic(null);
} else {
if (isEditing()) {
if (textField != null) {
textField.setText(getString());
// setGraphic(null);
}
setText(null);
setGraphic(textField);
} else {
setText(getString());
setGraphic(null);
}
}
}
private void createTextField() {
textField = new TextField(getString());
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textField.setOnAction((e) -> commitEdit(textField.getText()));
textField.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
if (!newValue) {
System.out.println("Commiting " + textField.getText());
commitEdit(textField.getText());
}
});
}
private String getString() {
return getItem() == null ? "" : getItem();
}
}
class DateEditingCell extends TableCell<Person, Date> {
private DatePicker datePicker;
private DateEditingCell() {
}
@Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createDatePicker();
setText(null);
setGraphic(datePicker);
}
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText(getDate().toString());
setGraphic(null);
}
@Override
public void updateItem(Date item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (datePicker != null) {
datePicker.setValue(getDate());
}
setText(null);
setGraphic(datePicker);
} else {
setText(getDate().format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)));
setGraphic(null);
}
}
}
private void createDatePicker() {
datePicker = new DatePicker(getDate());
datePicker.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
datePicker.setOnAction((e) -> {
System.out.println("Committed: " + datePicker.getValue().toString());
commitEdit(Date.from(datePicker.getValue().atStartOfDay(ZoneId.systemDefault()).toInstant()));
});
// datePicker.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
// if (!newValue) {
// commitEdit(Date.from(datePicker.getValue().atStartOfDay(ZoneId.systemDefault()).toInstant()));
// }
// });
}
private LocalDate getDate() {
return getItem() == null ? LocalDate.now() : getItem().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
}
class ComboBoxEditingCell extends TableCell<Person, Typ> {
private ComboBox<Typ> comboBox;
private ComboBoxEditingCell() {
}
@Override
public void startEdit() {
if (!isEmpty()) {
super.startEdit();
createComboBox();
setText(null);
setGraphic(comboBox);
}
}
@Override
public void cancelEdit() {
super.cancelEdit();
setText(getTyp().getTyp());
setGraphic(null);
}
@Override
public void updateItem(Typ item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
if (isEditing()) {
if (comboBox != null) {
comboBox.setValue(getTyp());
}
setText(getTyp().getTyp());
setGraphic(comboBox);
} else {
setText(getTyp().getTyp());
setGraphic(null);
}
}
}
private void createComboBox() {
comboBox = new ComboBox<>(typData);
comboBoxConverter(comboBox);
comboBox.valueProperty().set(getTyp());
comboBox.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
comboBox.setOnAction((e) -> {
System.out.println("Committed: " + comboBox.getSelectionModel().getSelectedItem());
commitEdit(comboBox.getSelectionModel().getSelectedItem());
});
// comboBox.focusedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
// if (!newValue) {
// commitEdit(comboBox.getSelectionModel().getSelectedItem());
// }
// });
}
private void comboBoxConverter(ComboBox<Typ> comboBox) {
// Define rendering of the list of values in ComboBox drop down.
comboBox.setCellFactory((c) -> {
return new ListCell<Typ>() {
@Override
protected void updateItem(Typ item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
} else {
setText(item.getTyp());
}
}
};
});
}
private Typ getTyp() {
return getItem() == null ? new Typ("") : getItem();
}
}
public static class Typ {
private final SimpleStringProperty typ;
public Typ(String typ) {
this.typ = new SimpleStringProperty(typ);
}
public String getTyp() {
return this.typ.get();
}
public StringProperty typProperty() {
return this.typ;
}
public void setTyp(String typ) {
this.typ.set(typ);
}
@Override
public String toString() {
return typ.get();
}
}
public static class Project {
private final SimpleStringProperty name;
private final SimpleListProperty<Person> persons;
public Project(String name, List<Person> persons) {
this.name = new SimpleStringProperty(name);
this.persons = new SimpleListProperty<>();
this.persons.setAll(persons);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return this.name;
}
public void setName(String name) {
this.name.set(name);
}
public List<Person> getPersons() {
return this.persons.get();
}
public SimpleListProperty<Person> personsProperty() {
return this.persons;
}
public void setPersons(List<Person> persons) {
this.persons.setAll(persons);
}
}
public static class Person {
private final SimpleStringProperty firstName;
private final SimpleObjectProperty<Typ> typ;
private final SimpleObjectProperty<Date> birthday;
public Person(String firstName, Typ typ, Date bithday) {
this.firstName = new SimpleStringProperty(firstName);
this.typ = new SimpleObjectProperty(typ);
this.birthday = new SimpleObjectProperty(bithday);
}
public String getFirstName() {
return firstName.get();
}
public StringProperty firstNameProperty() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName.set(firstName);
}
public Typ getTypObj() {
return typ.get();
}
public ObjectProperty<Typ> typObjProperty() {
return this.typ;
}
public void setTypObj(Typ typ) {
this.typ.set(typ);
}
public Date getBirthday() {
return birthday.get();
}
public ObjectProperty<Date> birthdayProperty() {
return this.birthday;
}
public void setBirthday(Date birthday) {
this.birthday.set(birthday);
}
}
}
@Lazdisas
Copy link

Good work,
Thank you.

@GetMaCuBeX
Copy link

,this won't work on JPA implimentation right?

@haisi
Copy link
Author

haisi commented Apr 25, 2020

@GetMaCuBeX
Copy link

,thanks bro.., i try ur link..,

@GetMaCuBeX
Copy link

2020-05-06 03_43_44-

@GetMaCuBeX
Copy link

,what i want bro is to make my date column editable and it has feature of datechooser.., sorry for my english grammng..,

@haisi
Copy link
Author

haisi commented May 31, 2020

@GetMaCuBeX line 230 describes how to create a DatePicker cell.

@kenmaready
Copy link

This is excellent. I just plugged-and-played the EditingCell class into my JavaFX project, changed one instantiation in my main controller to use the class, and it worked. Amazing. Thank you.

@JVamcas
Copy link

JVamcas commented Jan 13, 2021

Thank you man. I can actually give you 5USD for coffee. - Seriously.

@gituser2803966
Copy link

thanks bro ^_^

@ranjitvamadevan
Copy link

ranjitvamadevan commented Oct 26, 2022

i have build table cell edit based upon your code. i have used editable combobox in my code as table cell
I'd like to create a table with following features

  • Edit on key pressed

  • Enter key = next Row

  • Tab Key = next Column

  • Escape Key = Cancel Edit

    The Window Looks As Follows

ComboBox_1

The main problem that arises when we focus on combo box the focus moves out of the table. I want a solution that the focus remains in the table or to next cell in the table and commits the selected value of the combo box. The combo box is of the type Item
ComboBox<Item> items = new ComboBox<>();

The Table is as follows

 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; 

The purchase class is as follows

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);
}
}

The Item Class is as Follows

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);
}
}

The purchase model class

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;
}
}

The Controller Class is as follows

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);
    }
}

Please tell me a way to implement all the four points that i have mentioned above.
this question is been asked in stackoverflow. For comments and solution please visit:-
https://stackoverflow.com/questions/74180705/how-to-work-with-javafx-tableview-with-custom-table-cell-using-editable-combobox

@Rach-crypto
Copy link

I wonder how much time it took you to type it all

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment