I\'m trying to a add a Combo Box
to my Table View
:
Basically I have a class called TableViewTest that stores a name and a description, I ca
The types for your table column are always the type of the item in each row (i.e. the same as the type you use for the table view) for the first type parameter, and the type of the (current) value for each cell in the column for the second parameter. So if your table view has type TableViewTest
, and your combo box is selecting String
s, you should have:
TableColumn<TableViewTest, String> priceColumn ;
The cell value factory should still map to a property in the TableViewTest
class, i.e. assuming you have:
public class TableViewTest {
// ...
public StringProperty priceProperty() {
// ...
}
// ...
}
then you can do:
priceColumn.setCellValueFactory(new PropertyValueFactory<>("price"));
or (much better):
priceColumn.setCellValueFactory(cellData -> cellData.getValue().priceProperty());
Then you can just do:
priceColumn.setCellFactory(ComboBoxTableCell.forTableColumn(options));
Here's a SSCCE:
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TableWithComboBoxExample extends Application {
@Override
public void start(Stage primaryStage) {
TableView<Contact> contactTable = new TableView<>();
contactTable.setEditable(true);
TableColumn<Contact, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
contactTable.getColumns().add(nameCol);
TableColumn<Contact, String> categoryCol = new TableColumn<>("Category");
categoryCol.setCellValueFactory(cellData -> cellData.getValue().categoryProperty());
categoryCol.setCellFactory(ComboBoxTableCell.forTableColumn("Friends", "Family", "Work Contacts"));
contactTable.getColumns().add(categoryCol);
contactTable.getItems().addAll(
new Contact("Bill Gates", "Work Contacts"),
new Contact("Barack Obama", "Friends"),
new Contact("Tim Cook", "Work Contacts")
);
Scene scene = new Scene(new BorderPane(contactTable), 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class Contact {
private final StringProperty name = new SimpleStringProperty();
private final StringProperty category = new SimpleStringProperty();
public Contact(String name, String category) {
setName(name);
setCategory(category);
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final StringProperty categoryProperty() {
return this.category;
}
public final String getCategory() {
return this.categoryProperty().get();
}
public final void setCategory(final String category) {
this.categoryProperty().set(category);
}
}
public static void main(String[] args) {
launch(args);
}
}
James_D's answer works well, but requires the user to click on the item to see the ComboBox
. If you want to have ComboBox
es in a column, that are always shown, you have to use a custom cellFactory
:
public class TableViewTest {
...
private final StringProperty option = new SimpleStringProperty();
public String getOption() {
return option.get();
}
public void setOption(String value) {
option.set(value);
}
public StringProperty optionProperty() {
return option;
}
}
TableColumn<TableViewTest, StringProperty> column = new TableColumn<>("option");
column.setCellValueFactory(i -> {
final StringProperty value = i.getValue().optionProperty();
// binding to constant value
return Bindings.createObjectBinding(() -> value);
});
column.setCellFactory(col -> {
TableCell<TableViewTest, StringProperty> c = new TableCell<>();
final ComboBox<String> comboBox = new ComboBox<>(options);
c.itemProperty().addListener((observable, oldValue, newValue) -> {
if (oldValue != null) {
comboBox.valueProperty().unbindBidirectional(oldValue);
}
if (newValue != null) {
comboBox.valueProperty().bindBidirectional(newValue);
}
});
c.graphicProperty().bind(Bindings.when(c.emptyProperty()).then((Node) null).otherwise(comboBox));
return c;
});