JavaFX 中 tableview 单元格中的 ComboBox

新手上路,请多包涵

我正在尝试将 Combo Box 添加到我的 Table View

基本上我有一个名为 TableViewTest 的类,它存储名称和描述,我可以在 Table View 中显示这些名称和描述 --- 不用麻烦,但我想做的是添加第三列,每个单元格都有一个 Combo Box 以便用户可以从每个人的多个选项中选择一个。

到目前为止,我已经创建了一个 ObservableList 类型 String 具有一些值并将它们添加到 ComboBox 对象。有谁知道我可以将这个 Combo Box 添加到表中的方法吗?

还要记住这段代码非常粗糙,我只是想让一些东西工作,我会在以后重构代码。

 ObservableList<TableViewTest> products = FXCollections.observableArrayList();

    for(int i = 0; i < b.length; i++){

        // random String values
        products.add(new TableViewTest(b[i], a[i]));
    }

ObservableList<String> options = FXCollections.observableArrayList(
                                "1",
                                "2",
                                "3"
                                );
final ComboBox comboBox = new ComboBox(options);

TableColumn<TableViewTest, String> nameColumn = new TableColumn<> ("Name");
nameColumn.setMinWidth(200);
nameColumn.setCellValueFactory(new PropertyValueFactory<TableViewTest, String>("name"));

                //price Column
                //Stock Column
TableColumn<TableViewTest, String> StockColumn = new TableColumn<> ("Stock");
StockColumn.setMinWidth(150);
StockColumn.setCellValueFactory(new PropertyValueFactory<TableViewTest, String>("description"));

TableColumn<Object,ComboBox> PriceColumn;
PriceColumn = new TableColumn<>("Source");
PriceColumn.setMinWidth(150);
   //PriceColumn.setCellValueFactory(new PropertyValueFactory<>
   //(options));

   //PriceColumn.setCellFactory(ComboBoxTableCell.forTableColumn(new
   //DefaultStringConverter(), options));

   //PriceColumn.setCellFactory(ComboBoxTableCell.forTableColumn(
   //comboBox));

TableView<TableViewTest> table = new TableView<>();

table.setItems(products);
table.getColumns().addAll(nameColumn, StockColumn, PriceColumn);

原文由 noobCoder 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

James_D 的回答效果很好,但需要用户单击该项目才能看到 ComboBox 。如果您想在列中始终显示 ComboBox es,则必须使用自定义 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;
    });

原文由 fabian 发布,翻译遵循 CC BY-SA 4.0 许可协议

表列的类型始终是第一个类型参数的每行中项目的类型(即与您用于表视图的类型相同),以及每个单元格中的(当前)值的类型第二个参数的列。因此,如果您的表视图具有类型 TableViewTest ,并且您的组合框正在选择 String s,您应该具有:

 TableColumn<TableViewTest, String> priceColumn ;

单元格值工厂仍应映射到 TableViewTest 类中的一个属性,即假设您有:

 public class TableViewTest {

    // ...

    public StringProperty priceProperty() {
        // ...
    }

    // ...
}

然后你可以这样做:

 priceColumn.setCellValueFactory(new PropertyValueFactory<>("price"));

或者(更好):

 priceColumn.setCellValueFactory(cellData -> cellData.getValue().priceProperty());

然后你可以这样做:

 priceColumn.setCellFactory(ComboBoxTableCell.forTableColumn(options));

这是一个 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 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题