【问题标题】:Can I group rows in a Javafx TableView?我可以在 Javafx TableView 中对行进行分组吗?
【发布时间】:2019-10-09 13:17:21
【问题描述】:

我想制作一个 javafx TableView,其中的行可能(或可能没有)“相关”行。基本上,我认为它可能是 tableviews 的 tableview,但是 (a) 我不确定它会起作用,并且 (b) 我的直觉告诉我有一个更简单的方法。

想象一个帐单或类似的材料

item    material    quantity    name
1       wood        1           base
2       wood        4           drawer
        wood        4           drawer sides
        wood        1           drawer base
        hardware    1           pull
        hardware    8           nails
3       aluminum    4           leg
        plastic     1           foot
        hardware    1           screws

现在,它按名称(底座、抽屉、腿)排序。如果我按材料排序,我希望项目是 3、1、2(或 3、2、1):铝、木头、木头。我需要“子项目”与编号项目保持一致。

我可以制作“复杂的行”吗? (我什至不知道我会怎么称呼它!) 还是我需要一个自定义排序来将组保持在一起?

【问题讨论】:

标签: java javafx java-8 treeview tableview


【解决方案1】:

您可能想查看TreeTableView。有了它,您可以按您喜欢的任何标准进行排序,同时将记录按任何其他标准分组(例如按name

此组件从基于TreeItem 类的树结构模型中获取数据。

有了它,可以为您的物料清单的根对象构建一个根 TreeItem,作为子对象,您想要的每个组都有一个 TreeItem(材料名称?)。然后,这些分组TreeItem 对象中的每一个都应包含与正在显示的物料清单中每个实际material 对应的TreeItem 子对象作为子对象。

那里有多个很好的教程,详细介绍了这方面的技术方面:

希望这会有所帮助。

【讨论】:

  • 当我查看javafx 控件时,我看到TreeTableView 并认为它是一个TreeView,即没有列。这比我的选择要容易得多,谢谢你,Marco。
【解决方案2】:

此答案使用 TreeTableView 来表示数据,而不是 TableView。

它使用带有硬编码数据的演示数据模型。

复杂的嵌套 lambda 表达式可以替换为将您的实际模型数据映射到支持 TreeTableView 的 TreeItem 数据结构的过程代码。

import java.util.*;

import javafx.application.Application;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;

@SuppressWarnings("unchecked")
public class TreeTableViewSample extends Application {

    private final List<String> employeesNames = Arrays.asList(
            "Ethan Williams",
            "Emma Jones",
            "Michael Brown"
    );

    private final Random random = new Random(42);

    @Override
    public void start(Stage stage) {
        ObservableList<DutyAssignment> assignments =
                determineAssignments(employeesNames);

        TreeItem<DutyAssignment> assignmentTree = createAssignmentTree(assignments);
        TreeTableView<DutyAssignment> dutyAssignmentView = createAssigmentTreeTableView(assignmentTree);

        stage.setScene(new Scene(dutyAssignmentView));
        stage.show();
    }

    private TreeTableView<DutyAssignment> createAssigmentTreeTableView(TreeItem<DutyAssignment> root) {
        TreeTableColumn<DutyAssignment, String> employeeColumn =
                new TreeTableColumn<>("Employee");
        employeeColumn.setPrefWidth(120);
        employeeColumn.setCellValueFactory(
                param -> param.getValue().getValue().nameProperty()
        );

        TreeTableColumn<DutyAssignment, Workday> dayColumn =
                new TreeTableColumn<>("Day");
        dayColumn.setPrefWidth(100);
        dayColumn.setCellValueFactory(param ->
                param.getValue().getValue().dayProperty()
        );

        TreeTableColumn<DutyAssignment, Duty> dutyColumn =
                new TreeTableColumn<>("Duty");
        dutyColumn.setPrefWidth(100);
        dutyColumn.setCellValueFactory(param ->
                param.getValue().getValue().dutyProperty()
        );

        TreeTableView<DutyAssignment> dutyAssignmentView = new TreeTableView<>(root);
        dutyAssignmentView.getColumns().setAll(employeeColumn, dayColumn, dutyColumn);
        dutyAssignmentView.setShowRoot(false);
        dutyAssignmentView.setPrefSize(380, 500);
        
        return dutyAssignmentView;
    }

    private TreeItem<DutyAssignment> createAssignmentTree(ObservableList<DutyAssignment> assignments) {
        TreeItem<DutyAssignment> root = new TreeItem<>(
                new DutyAssignment("All Assignments", null, null)
        );
        root.setExpanded(true);
        employeesNames.stream()
                .sorted()
                .forEach(employeeName -> {
                    TreeItem<DutyAssignment> employeeTitleItem = new TreeItem<>(
                            new DutyAssignment(employeeName, null, null)
                    );
                    root.getChildren().add(employeeTitleItem);
                    employeeTitleItem.setExpanded(true);

                    assignments.stream()
                            .sorted()
                            .filter(assignment -> employeeName.equals(assignment.getName()))
                            .forEach(dutyAssignment -> {
                                TreeItem<DutyAssignment> assignmentLineItem = new TreeItem<>(
                                        new DutyAssignment(null, dutyAssignment.getDay(), dutyAssignment.getDuty())
                                );
                                employeeTitleItem.getChildren().add(assignmentLineItem);
                            });
                });
        
        return root;
    }

    private ObservableList<DutyAssignment> determineAssignments(List<String> employeesNames) {
        ObservableList<DutyAssignment> assignments = FXCollections.observableArrayList();

        for (String employeeName : employeesNames) {
            for (Workday day : Workday.values()) {
                assignments.add(
                        new DutyAssignment(
                                employeeName,
                                day,
                                selectRandomDuty()
                        )
                );
            }
        }

        return assignments;
    }

    private Duty selectRandomDuty() {
        return
                Duty.values()[
                        random.nextInt(
                                Duty.values().length
                        )
                ];
    }

    public static void main(String[] args) {
        Application.launch(TreeTableViewSample.class, args);
    }

    public class DutyAssignment implements Comparable<DutyAssignment> {
        final private SimpleStringProperty name = new SimpleStringProperty();
        final private SimpleObjectProperty<Workday> day = new SimpleObjectProperty<>();
        final private SimpleObjectProperty<Duty> duty = new SimpleObjectProperty<>();

        final private Comparator<DutyAssignment> nameDayDutyComparator =
                Comparator.comparing(DutyAssignment::getName)
                        .thenComparing(DutyAssignment::getDay)
                        .thenComparing(DutyAssignment::getDuty);

        public DutyAssignment(String name, Workday day, Duty duty) {
            setName(name);
            setDay(day);
            setDuty(duty);
        }

        public String getName() {
            return name.get();
        }

        public SimpleStringProperty nameProperty() {
            return name;
        }

        public void setName(String name) {
            this.name.set(name);
        }

        public Workday getDay() {
            return day.get();
        }

        public SimpleObjectProperty<Workday> dayProperty() {
            return day;
        }

        public void setDay(Workday day) {
            this.day.set(day);
        }

        public Duty getDuty() {
            return duty.get();
        }

        public SimpleObjectProperty<Duty> dutyProperty() {
            return duty;
        }

        public void setDuty(Duty duty) {
            this.duty.set(duty);
        }

        @Override
        public int compareTo(DutyAssignment o) {
            return nameDayDutyComparator.compare(this, o);
        }
    }

    public enum Duty {
        WRITING, EDITING, COLORING, COMPOSITING
    }

    public enum Workday {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY
    }
}

【讨论】:

    猜你喜欢
    • 2021-01-14
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多