【问题标题】:Dynamic cell drop-down in javafx tableview [closed]javafx tableview中的动态单元格下拉菜单[关闭]
【发布时间】:2021-11-04 01:38:51
【问题描述】:

我有一个表,其中几列是组合框类型。现在我不希望这些列表在加载表时是静态的。如果我在 cell1 中选择一个值,则基于应该填充 cell2 的哪个下拉列表。我们怎样才能做到这一点?

【问题讨论】:

标签: javafx tableview tablecell


【解决方案1】:

表格中的通用(非依赖)组合框选择

此答案基于对 James 对以下问题的回答的修改:

因此,您可以参考该解决方案以获取更多上下文信息。

本例说明

在示例中,我们有第一个下拉菜单,用于选择与指定人员的关系。还有第二个下拉菜单,用于提供给指定人员的礼物。

可用礼物的选择取决于关系,关系越密切,可用礼物的价值越高。

下图显示了在“关系”列中编辑值时可供选择的选项。这些选择是固定的,不会改变:

下图显示了在礼品列中编辑值时可供选择的选项,用于选定的家庭关系:

下图显示了在编辑礼物列中的值时可供选择的选项,用于所选的 ACQUAINTANCE 关系:

工作原理

ComboBoxTableCell 用于生成用于编辑选择的单元工厂。

枚举用于表示关系和礼物的不同选择类型。但是如果你想要一个更动态的设置和更少的静态类型,你可以只使用字符串而不是枚举。

public enum GiftType {
    TOY, COFFEE, DINNER, VACATION
}

public enum RelationshipType {
    FAMILY, FRIEND, ACQUAINTANCE;
}

关系的选择,只有一个静态的选择列表,使用CombBoxTableCell,不做任何修改:

TableColumn<Contact, Contact.RelationshipType> relationshipCol = 
    new TableColumn<>("Relationship");
relationshipCol.setCellValueFactory(cellData ->
    cellData.getValue().relationshipProperty()
);
relationshipCol.setCellFactory(
    ComboBoxTableCell.forTableColumn(
          Contact.RelationshipType.values()
    )
);

礼物的选择取决于选择的关系,因此需要更多的工作来实现:

TableColumn<Contact, Contact.GiftType> giftCol = 
    new TableColumn<>("Gift");
giftCol.setCellValueFactory(cellData -> 
    cellData.getValue().giftProperty()
);
giftCol.setCellFactory(this::giftCellFactory);

giftCellFactory 在哪里:

private TableCell<Contact, Contact.GiftType> giftCellFactory(
  TableColumn<Contact, Contact.GiftType> list
) {
    return new ComboBoxTableCell<>() {
        @Override
        public void startEdit() {
            getItems().setAll(
                    getTableRow().getItem().getAvailableGifts()
            );
            super.startEdit();
        }
    };
}

礼品单元工厂正在做的是监听礼品单元编辑事件的开始。当编辑开始时,它会更新可供选择的可用礼物值列表,以将它们限制为仅可用于项目的所选关系类型的可用礼物。这样,当编辑 ComboBox 出现时,它只会显示给定关系的有效选择。

关系和礼物的显示只是依靠枚举类型的标准toString值。但是,如果您想自定义值(例如更改大小写,或将所选代码映射到值),则可以将 StringConverter 提供给 constructor of the CombBoxTableCell

为了让这个功能发挥作用,在模型类(在本例中是一个名为 Contact 的类)中,我们提供了许多工具。

  1. 我们将所有值表示为具有 getter/setter 和属性访问器的属性。

  2. 我们为关系属性提供了一个监听器。

    在侦听器中,如果关系发生变化并且这将导致该关系类型的礼物值无效,则该联系人的当前礼物设置为 null。

    relationshipProperty().addListener((observable, oldValue, newValue) -> {
        if (availableGifts.get(newValue) == null || !availableGifts.get(newValue).contains(getGift())) {
            setGift(null);
        }
    });
    
  3. 我们提供与可用礼物类型的关系映射。

    为了允许为给定联系人选择不礼物,我们在每个可用的礼物选择列表中放置一个空值。如果我们想要一份礼物,而不是让它成为可选项,那么我们就不会在礼物选项列表中提供空值供选择。

    对于这个映射,我们有访问器允许:

    • 检索任何给定关系类型的所有礼物,以及
    • 为此联系人选择的当前关系可用的礼物。

    此示例中的映射位于 Contact 模型类中,但如果您愿意,您可以在其他地方管理映射(例如,在单独的数据库关系中)。

    private static final Map<RelationshipType, List<GiftType>> availableGifts = Map.of(
            RelationshipType.FAMILY, Arrays.asList(null, GiftType.TOY, GiftType.DINNER, GiftType.VACATION),
            RelationshipType.FRIEND, Arrays.asList(null, GiftType.TOY, GiftType.COFFEE, GiftType.DINNER),
            RelationshipType.ACQUAINTANCE, Arrays.asList(null, GiftType.COFFEE)
    );
    
    public static List<GiftType> listAvailableGiftsForRelationshipType(RelationshipType relationshipType) {
        return availableGifts.get(relationshipType);
    }
    
    public List<GiftType> getAvailableGifts() {
        return availableGifts.get(getRelationship());
    }
    

示例代码

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.*;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.util.*;

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, Contact.RelationshipType> relationshipCol = new TableColumn<>("Relationship");
        relationshipCol.setCellValueFactory(cellData -> cellData.getValue().relationshipProperty());
        relationshipCol.setCellFactory(ComboBoxTableCell.forTableColumn(Contact.RelationshipType.values()));
        relationshipCol.setPrefWidth(150);
        contactTable.getColumns().add(relationshipCol);

        TableColumn<Contact, Contact.GiftType> giftCol = new TableColumn<>("Gift");
        giftCol.setCellValueFactory(cellData -> cellData.getValue().giftProperty());
        giftCol.setCellFactory(this::giftCellFactory);
        giftCol.setPrefWidth(120);
        contactTable.getColumns().add(giftCol);

        contactTable.getItems().addAll(
                new Contact("Braxton Walls", Contact.RelationshipType.FAMILY, Contact.GiftType.VACATION),
                new Contact("Zainab Berger", Contact.RelationshipType.ACQUAINTANCE, null),
                new Contact("Safiyah Hail", Contact.RelationshipType.FRIEND, Contact.GiftType.DINNER),
                new Contact("Akbar Storey", Contact.RelationshipType.ACQUAINTANCE, null)
        );
        contactTable.setPrefSize(400, 200);

        Scene scene = new Scene(new BorderPane(contactTable));
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TableCell<Contact, Contact.GiftType> giftCellFactory(TableColumn<Contact, Contact.GiftType> list) {
        return new ComboBoxTableCell<>() {
            @Override
            public void startEdit() {
                getItems().setAll(
                        getTableRow().getItem().getAvailableGifts()
                );
                super.startEdit();
            }
        };
    }

    public static class Contact {
        public enum GiftType {
            TOY, COFFEE, DINNER, VACATION
        }

        public enum RelationshipType {
            FAMILY, FRIEND, ACQUAINTANCE;
        }

        private static final Map<RelationshipType, List<GiftType>> availableGifts = Map.of(
                RelationshipType.FAMILY, Arrays.asList(null, GiftType.TOY, GiftType.DINNER, GiftType.VACATION),
                RelationshipType.FRIEND, Arrays.asList(null, GiftType.TOY, GiftType.COFFEE, GiftType.DINNER),
                RelationshipType.ACQUAINTANCE, Arrays.asList(null, GiftType.COFFEE)
        );

        private final StringProperty name = new SimpleStringProperty();
        private final ObjectProperty<RelationshipType> relationship = new SimpleObjectProperty<>();
        private final ObjectProperty<GiftType> gift = new SimpleObjectProperty<>();

        public Contact(String name, RelationshipType relationship, GiftType gift) {
            setName(name);
            setRelationship(relationship);
            relationshipProperty().addListener((observable, oldValue, newValue) -> {
                if (availableGifts.get(newValue) == null || !availableGifts.get(newValue).contains(getGift())) {
                    setGift(null);
                }
            });
            setGift(gift);
        }

        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 ObjectProperty<RelationshipType> relationshipProperty() {
            return this.relationship;
        }
        public final RelationshipType getRelationship() {
            return this.relationshipProperty().get();
        }
        public final void setRelationship(final RelationshipType relationship) {
            this.relationshipProperty().set(relationship);
        }

        public final ObjectProperty<GiftType> giftProperty() {
            return this.gift;
        }
        public final GiftType getGift() {
            return this.giftProperty().get();
        }
        public final void setGift(final GiftType gift) {
            this.giftProperty().set(gift);
        }

        public static List<GiftType> listAvailableGiftsForRelationshipType(RelationshipType relationshipType) {
            return availableGifts.get(relationshipType);
        }

        public List<GiftType> getAvailableGifts() {
            return availableGifts.get(getRelationship());
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

【讨论】:

    猜你喜欢
    • 2013-08-09
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 2021-11-17
    • 1970-01-01
    相关资源
    最近更新 更多