我正在创建一个 javafx/fxml 应用程序。我有一个显示名字、姓氏和 ID 的下拉列表。我希望下拉列表具有每列的标题,并在相应的列中显示数据。我将如何创建这个下拉菜单?
我尝试在组合框中创建列表视图,但无法正常工作。我也尝试过使用表格视图,但我也无法正常工作。
您可以将单元工厂设置为 ComboBox,以您想要的方式创建单元。然而,实现标题并仅滚动值单元格会很棘手。
为了让事情简单,我宁愿使用一个自定义实现,它看起来像一个下拉列表,但使用一些不同的节点构建。
总体思路是:
TableView
中显示 Popup
。请查看下面的演示。如果这不能满足您的需求,那么我认为您需要使用细胞工厂实现。
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);
}
}
}