I'm creating a javafx/fxml app. I have a dropdown that displays first name, last name and and ID. I want the dropdown to have the headers for each column and also display the data in that appropriate column. How would I go about creating this dropdown?
I have tried created a list view within the combo box and that didn't work properly. I have also tried to use the tableview and that I cannot also get to work appropriately.
You can set a cell factory to the ComboBox that creates the cells in the way you are looking for. However it will be tricky to implement the headers and scroll only the value cells.
To keep the things simple, I would rather go with a custom implementation that looks like a drop-down but built with some different nodes.
The general idea is:
TableView
in a Popup
that is placed at the bottom of the button.Please check the below demo. If this doesn't suite your needs, then I think you need to go with the cell factory implementation.
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Bounds;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;
public class DropDownWithTableDemo extends Application {
String defaultVal = "Select...";
ObjectProperty<TableObj> valueObj = new SimpleObjectProperty<>();
@Override
public void start(Stage primaryStage) throws Exception {
TableView<TableObj> tableView = buildTable(valueObj);
Popup popup = new Popup();
popup.getContent().add(tableView);
popup.setAutoHide(true);
Label valueLabel = new Label(defaultVal);
valueLabel.setMaxWidth(Double.POSITIVE_INFINITY);
HBox.setHgrow(valueLabel, Priority.ALWAYS);
StackPane arrow = new StackPane();
arrow.setStyle("-fx-background-color:#444444;-fx-shape:\"M 0 0 h 7 l -3.5 4 z\";-fx-padding: 4px;");
arrow.setMaxSize(8, 8);
HBox pane = new HBox(10, valueLabel, arrow);
pane.setAlignment(Pos.CENTER_LEFT);
pane.setMaxWidth(Double.POSITIVE_INFINITY);
Button dropDownBtn = new Button();
dropDownBtn.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
dropDownBtn.setPrefWidth(150);
dropDownBtn.setGraphic(pane);
dropDownBtn.setOnMouseClicked(e -> {
if (!popup.isShowing()) {
Bounds bounds = dropDownBtn.localToScreen(dropDownBtn.getLayoutBounds());
popup.show(dropDownBtn, bounds.getMinX(), bounds.getMaxY());
}
});
valueObj.addListener((obs, old, val) -> {
if (val != null) {
valueLabel.setText(val.firstName.getValue());
} else {
valueLabel.setText(defaultVal);
}
popup.hide();
});
Scene scene = new Scene(new StackPane(dropDownBtn), 400, 200);
primaryStage.setTitle("TableView DropDown");
primaryStage.setScene(scene);
primaryStage.show();
}
private TableView<TableObj> buildTable(ObjectProperty<TableObj> valueObj) {
TableView<TableObj> tableView = new TableView<>();
TableColumn<TableObj, String> idCol = new TableColumn<>("ID");
TableColumn<TableObj, String> fnCol = new TableColumn<>("First Name");
TableColumn<TableObj, String> lnCol = new TableColumn<>("Last Name");
idCol.setCellValueFactory(p -> p.getValue().id);
fnCol.setCellValueFactory(p -> p.getValue().firstName);
lnCol.setCellValueFactory(p -> p.getValue().lastName);
ObservableList<TableObj> items = FXCollections.observableArrayList();
for (int x = 1; x < 50; x++) {
items.add(new TableObj("" + x, "First " + x, "Last " + x));
}
tableView.getColumns().addAll(idCol, fnCol, lnCol);
tableView.setItems(items);
tableView.setRowFactory(param -> new TableRow<>() {
{
setOnMouseClicked(e -> {
if (getItem() != null) {
valueObj.set(getItem());
}
});
}
});
return tableView;
}
class TableObj {
private StringProperty id;
private StringProperty firstName;
private StringProperty lastName;
public TableObj(String test1, String test2, String test3) {
this.id = new SimpleStringProperty(test1);
this.firstName = new SimpleStringProperty(test2);
this.lastName = new SimpleStringProperty(test3);
}
}
}