ComboBox in a tableview cell in JavaFX

后端 未结 2 996
一个人的身影
一个人的身影 2021-01-13 11:38

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

相关标签:
2条回答
  • 2021-01-13 12:16

    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 Strings, 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);
        }
    }
    
    0 讨论(0)
  • 2021-01-13 12:30

    James_D's answer works well, but requires the user to click on the item to see the ComboBox. If you want to have ComboBoxes in a column, that are always shown, you have to use a custom cellFactory:

    Example:

    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;
        });
    
    0 讨论(0)
提交回复
热议问题