Java Vaadin 8.1树形网格基于列的过滤

Java Vaadin 8.1树形网格基于列的过滤,java,vaadin,vaadin8,Java,Vaadin,Vaadin8,我需要根据列过滤树网格。我遵循了上面提到的解决方案。我尝试了下面的代码片段进行过滤,但是它没有显示任何数据 TreeDataProvider<Project> dataProvider = new TreeDataProvider<>(treeGrid.getTreeData()); dataProvider.setFilter(Project -> (Project.getStatus() != null && Project.getStatus(

我需要根据列过滤树网格。我遵循了上面提到的解决方案。我尝试了下面的代码片段进行过滤,但是它没有显示任何数据

TreeDataProvider<Project> dataProvider = new TreeDataProvider<>(treeGrid.getTreeData());
dataProvider.setFilter(Project -> (Project.getStatus() != null && Project.getStatus().equals(Project.Status.PASS)));
treeGrid.setDataProvider(dataProvider);
treeGrid.getDataProvider().refreshAll();
TreeDataProvider数据提供者=新的TreeDataProvider(treeGrid.getTreeData());
dataProvider.setFilter(Project->(Project.getStatus()!=null&&Project.getStatus().equals(Project.Status.PASS));
treeGrid.setDataProvider(数据提供者);
treeGrid.getDataProvider().refreshAll();

是否有其他方法可以使用vaadin 8.1树形网格过滤数据。

您的问题最有可能出现

dataProvider.setFilter(Project->(Project.getStatus()!=null&&Project.getStatus().equals(Project.Status.PASS));
我假设根节点和中间节点的状态为空,因此它们与筛选器不匹配,因此它们的子节点将不会显示


为了简单起见,您可以允许状态为null的项目,或者与筛选器匹配,但有时您可能会以空的中间节点结束,因为没有子节点与筛选器匹配:

dataProvider.setFilter(Project -> (Project.getStatus() == null || Project.getStatus().equals(Project.Status.PASS)));


防弹解决方案有点棘手,因为您需要允许层次结构中至少有一个子节点与过滤器匹配。这可能有些过分,但这是我能想到的使用内存数据的最快方法,所以任何有改进建议的人,请分享。如果数据是从DB查询中筛选出来的,您可能就不需要这样做了

无论如何,我在
Project
中添加了一个
flatten
方法,显然,该方法将项目层次结构展平为一个项目流,您可以快速遍历这些项目,并查看它们是否与您的过滤器匹配。下面是基于的完整实现。我还改变了数据最初输入树网格的方式,因此您不必进行类似
newtreedataprovider(treeGrid.getTreeData())的黑客操作

import com.vaadin.data.TreeData;
导入com.vaadin.data.provider.TreeDataProvider;
导入com.vaadin.ui.ComboBox;
导入com.vaadin.ui.Notification;
导入com.vaadin.ui.TreeGrid;
导入com.vaadin.ui.VerticalLayout;
导入java.util.*;
导入java.util.stream.stream;
公共类BasicTreeGrid扩展了垂直布局{
//用于生成一些随机数据
私有最终随机=新随机();
公共基本网格(){
//基本设置
设置大小();
TreeGrid TreeGrid=新的TreeGrid();
treeGrid.setSizell();
addComponent(treeGrid);
treeGrid.addColumn(Project::getName).setCaption(“Project Name”).setId(“Name column”);
treeGrid.addColumn(项目::getHoursDone.setCaption(“hoursdone”).setId(“hourcolumn”);
treeGrid.addColumn(项目::getLastModified).setCaption(“上次修改”).setId(“日期列”);
treeGrid.addColumn(Project::getStatus).setCaption(“Status”).setId(“Status column”);
//一些听众需要互动
treeGrid.addCollapseListener(事件->通知
.show(“项目“+”事件.getCollapsedItem().getName()+”“折叠”,通知.Type.TRAY_通知));
treeGrid.addExpandListener(事件->通知
.show(“项目“+”事件.getExpandedItem().getName()+”“已展开”,通知.Type.TRAY_通知));
//添加根项目列表并指定子项目的提供程序
TreeData=新的TreeData();
数据.附加项(GenerateProjectsForyers(2010、2016),项目::getSubProjects);
TreeDataProvider=新的TreeDataProvider(数据);
treeGrid.setDataProvider(数据提供者);
//过滤器组合设置
ComboBox statusFilter=新建ComboBox();
statusFilter.setItems(Status.values());
statusFilter.setEmptySelectionCaption(“全部”);
statusFilter.addValueChangeListener(事件->{
if(event.getValue()==null){
dataProvider.clearFilters();
}否则{
dataProvider.setFilter(项目->{
if(project.getSubProjects()==null | project.getSubProjects().isEmpty()){
//包括与过滤器匹配的最终节点
返回project.getStatus()==null | | project.getStatus()==event.getValue();
}否则{
//包括具有与筛选器匹配的子节点的根节点和中间节点
返回project.flatte().anyMatch(subProject->subProject.getStatus()==event.getValue());
}
});
}
});
//将筛选器组合添加到标题
treeGrid.appendHeaderRow().getCell(“状态列”).setComponent(状态过滤器);
}
//生成一些随机项目
私有列表GenerateProjectsForyear(int startYear,int endYear){
列表项目=新建ArrayList();
for(int year=startYear;year project.getHoursDone()).reduce(0,Integer::sum);
}
公共日期getLastModified(){
返回getSubProjects().stream().map(project->project.getLastModified()).max(日期::compareTo).orElse(null);
}
公共状态getStatus(){
返回状态;
}
公共无效设置状态(状态){
这个状态=状态;
}
//将项目层次结构展平为项目流
公共河流变平(){
返回流.concat(
(这个)流,
subProjects.stream().flatMap(Project::flatte));
}
}
//用于轻松绑定的基本最终子(不能有其他子)bean
类LeafProject扩展项目{
私人室内活动时间;
上次修改的私人日期;
公共项目(字符串名称、整数小时完成、整数年、状态){
超级(姓名);
设置状态(状态);
this.hoursDone=hoursDone;
import com.vaadin.data.TreeData;
import com.vaadin.data.provider.TreeDataProvider;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TreeGrid;
import com.vaadin.ui.VerticalLayout;

import java.util.*;
import java.util.stream.Stream;

public class BasicTreeGrid extends VerticalLayout {

    // used to generate some random data
    private final Random random = new Random();

    public BasicTreeGrid() {
        // basic setup
        setSizeFull();
        TreeGrid<Project> treeGrid = new TreeGrid<>();
        treeGrid.setSizeFull();
        addComponent(treeGrid);
        treeGrid.addColumn(Project::getName).setCaption("Project Name").setId("name-column");
        treeGrid.addColumn(Project::getHoursDone).setCaption("Hours Done").setId("hour-column");
        treeGrid.addColumn(Project::getLastModified).setCaption("Last Modified").setId("date-column");
        treeGrid.addColumn(Project::getStatus).setCaption("Status").setId("status-column");

        // some listeners for interaction
        treeGrid.addCollapseListener(event -> Notification
                .show("Project '" + event.getCollapsedItem().getName() + "' collapsed.", Notification.Type.TRAY_NOTIFICATION));
        treeGrid.addExpandListener(event -> Notification
                .show("Project '" + event.getExpandedItem().getName() + "' expanded.", Notification.Type.TRAY_NOTIFICATION));


        // add the list of root projects and specify a provider of sub-projects
        TreeData<Project> data = new TreeData<>();
        data.addItems(generateProjectsForYears(2010, 2016), Project::getSubProjects);
        TreeDataProvider<Project> dataProvider = new TreeDataProvider<>(data);
        treeGrid.setDataProvider(dataProvider);

        // filter combo setup
        ComboBox<Status> statusFilter = new ComboBox<>();
        statusFilter.setItems(Status.values());
        statusFilter.setEmptySelectionCaption("ALL");
        statusFilter.addValueChangeListener(event -> {
            if (event.getValue() == null) {
                dataProvider.clearFilters();
            } else {
                dataProvider.setFilter(project -> {
                    if (project.getSubProjects() == null | project.getSubProjects().isEmpty()) {
                        // include final nodes matching the filter
                        return project.getStatus() == null || project.getStatus() == event.getValue();
                    } else {
                        // include root and intermediate nodes that have children matching the filter
                        return project.flatten().anyMatch(subProject -> subProject.getStatus() == event.getValue());
                    }
                });
            }
        });

        // add filter combo to header
        treeGrid.appendHeaderRow().getCell("status-column").setComponent(statusFilter);
    }

    // generate some random projects
    private List<Project> generateProjectsForYears(int startYear, int endYear) {
        List<Project> projects = new ArrayList<>();

        for (int year = startYear; year <= endYear; year++) {
            Project yearProject = new Project("Year " + year);

            for (int i = 1; i < 2 + random.nextInt(5); i++) {
                Project customerProject = new Project("Customer Project " + i);
                customerProject.setSubProjects(Arrays.asList(
                        new LeafProject("Implementation", random.nextInt(100), year, Status.values()[random.nextInt(3)]),
                        new LeafProject("Planning", random.nextInt(10), year, Status.values()[random.nextInt(3)]),
                        new LeafProject("Prototyping", random.nextInt(20), year, Status.values()[random.nextInt(3)])));
                yearProject.addSubProject(customerProject);
            }
            projects.add(yearProject);
        }
        return projects;
    }

    // project status
    enum Status {
        NOT_STARTED, IN_PROGRESS, DONE
    }

    // basic parent (or intermediate child) bean used for easy binding
    class Project {
        private List<Project> subProjects = new ArrayList<>();
        private String name;
        private Status status;

        public Project(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public List<Project> getSubProjects() {
            return subProjects;
        }

        public void setSubProjects(List<Project> subProjects) {
            this.subProjects = subProjects;
        }

        public void addSubProject(Project subProject) {
            subProjects.add(subProject);
        }

        public int getHoursDone() {
            return getSubProjects().stream().map(project -> project.getHoursDone()).reduce(0, Integer::sum);
        }

        public Date getLastModified() {
            return getSubProjects().stream().map(project -> project.getLastModified()).max(Date::compareTo).orElse(null);
        }

        public Status getStatus() {
            return status;
        }

        public void setStatus(Status status) {
            this.status = status;
        }

        // flatten the project hierarchy into a stream of items
        public Stream<Project> flatten() {
            return Stream.concat(
                    Stream.of(this),
                    subProjects.stream().flatMap(Project::flatten));
        }
    }


    // basic final child (can not have other children) bean used for easy binding
    class LeafProject extends Project {
        private int hoursDone;
        private Date lastModified;

        public LeafProject(String name, int hoursDone, int year, Status status) {
            super(name);
            setStatus(status);
            this.hoursDone = hoursDone;
            lastModified = new Date(year - 1900, random.nextInt(12), random.nextInt(10));
        }

        @Override
        public int getHoursDone() {
            return hoursDone;
        }

        @Override
        public Date getLastModified() {
            return lastModified;
        }
    }
}