如何反转vaadin Grid?

时间:2017-03-28 15:42:04

标签: java vaadin vaadin-grid

我正在尝试使用Spring Boot和Vaadin构建一个简单的Java应用程序。 我需要在UI上添加一个表格,如下所示:https://www.screencast.com/t/1c4xkr4IE

它可以延长一段时间。

看起来Vaadin Grid元素完全符合我的要求,但它将我的行添加为列。是否有可能反转网格或者还有另一种方法来构建所需的表?

更新

以下是我的代码:

@SpringComponent
@UIScope
public class MyDataEditor extends VerticalLayout {
private final MyDataRepository repository;
private MyData myData;

TextField month = new TextField("Period");
TextField numberOfWorkers = new TextField(" Number of workers");
TextField numberOfNewcomers = new TextField("Number of newcomers");
TextField numberOfDismissals = new TextField("Number of dismissals");

Button save = new Button("Save");
Button cancel = new Button("Cancel");
Button delete = new Button("Delete");
CssLayout actions = new CssLayout(save, cancel, delete);

Binder<MyData> binder = new Binder<>(MyData.class);

@Autowired
public MyDataEditor(MyDataRepository repository) {
    this.repository = repository;
    addComponents(month, numberOfWorkers, numberOfNewcomers, numberOfDismissals, actions);
    binder.bindInstanceFields(this); 
    setSpacing(true);
    actions.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
    save.setStyleName(ValoTheme.BUTTON_PRIMARY);
    save.setClickShortcut(ShortcutAction.KeyCode.ENTER);

    save.addClickListener(e -> repository.save(myData));
    delete.addClickListener(e -> repository.delete(myData));
    cancel.addClickListener(e -> editInputData(myData));
    setVisible(false);
}

public interface ChangeHandler {
    void onChange();
}

public final void editMyData(MyData c) {
    if (c == null) {
        setVisible(false);
        return;
    }
    final boolean persisted = c.getMonth() != null;
    if (persisted) {
        myData = repository.findOne(c.getMonth());
    } else {
        myData = c;
    }
    cancel.setVisible(persisted);
    binder.setBean(myData);
    save.focus();
    periodId.selectAll();
}

public void setChangeHandler(ChangeHandler h) {
    save.addClickListener(e -> h.onChange());
    delete.addClickListener(e -> h.onChange());
}

}


@SpringUI
@Theme("valo")
public class VaadinUI extends UI {
private final MyDataRepository repo;
private final MyDataEditor editor;
final Grid<MyData> grid;
private final Button addNewBtn;

@Autowired
public VaadinUI(MyDataRepository repo, MyDataEditor editor) {
    this.repo = repo;
    this.editor = editor;
    this.grid = new Grid<>(MyData.class);
    this.addNewBtn = new Button("Add new month");
}

@Override
protected void init(VaadinRequest request) {

    grid.setHeight(300, Unit.PIXELS);
    grid.setColumns("month", "numberOfWorkers", "numberOfNewcomers", "numberOfDismissals");
    grid.asSingleSelect().addValueChangeListener(e -> {
        editor.editMyData(e.getValue());
    });
    addNewBtn.addClickListener(e -> editor.editMyData(new MyData()));
    editor.setChangeHandler(() -> {
        editor.setVisible(false);
        grid.setItems(repo.findAll());
    });
}
}

所以我的意思是这个问题是我设置

grid.setColumns("month", "numberOfWorkers", "numberOfNewcomers", "numberOfDismissals");

并且找不到类似setRows的方法,因此我的表格如下:https://www.screencast.com/t/ndDY6tXp,但应该像第一张图片一样。

2 个答案:

答案 0 :(得分:0)

我相信没有CSS或扩展客户端网格组件就没有办法优雅地解决它。

您可以做的是使用

添加数据
List<MyData> data = repo.findAll();
for(int i = 0; i < data.size(); i++)
    grid.addColumn(i)

//String[] months = data.map(x -> x.month).collect(Collectors.toArray)
//String[] nrWork = data.map(x -> x.nrWork).collect(Collectors.toArray)
grid.addRow(months)
grid.addRow(nrWork)

答案 1 :(得分:0)

我认为Vaadin grid(或表)组件的设计以table concept为起点。因此,您将拥有由列定义的统一结构,并显示任意数量的相同类型数据元素,每行1个。据我所知,高达8.0.4,您无法旋转结构。

此外,从用户体验的角度来看,如果您有多个时间段,则垂直(使用鼠标滚轮)滚动它们比使用水平更容易,因此,我建议讨论在开始时显示它们的可能性,包括“月”,“numberOfWorkers”,“numberOfNewcomers”和“numberOfDismissals”列,以及提供MyData行。这也使得对所选项目进行排序,过滤,添加或编辑变得更加容易,而对于下面的解决方法,您必须做一些额外的工作。

如果由于某种原因这根本不可接受,你应该能够通过一些工作伪造你想要的功能(见下面的样本),但性能和可用性明智,不能保证......毕竟,这个不是它的设计目标。

<强>代码

package com.example.grid;

import com.vaadin.data.ValueProvider;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Notification;
import com.vaadin.ui.VerticalLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;

public class HorizontalGrid extends VerticalLayout {

    private static final String ROW_CAPTION = "row-caption";

    public HorizontalGrid() {
        // basic grid setup without column header
        Grid<HorizontalDisplayAdapter> grid = new Grid<>();
        grid.setSizeFull();
        grid.setSelectionMode(Grid.SelectionMode.NONE);
        grid.removeHeaderRow(0);

        // load some data from the DB or someplace else
        List<PeriodSummary> periods = loadPeriods();

        // add row headers
        grid.addColumn(HorizontalDisplayAdapter::getCaption).setId(ROW_CAPTION).setWidth(150);

        // add a column for each period
        for (int i = 0; i < periods.size(); i++) {
            // save the column index so we ca figure out what to edit later
            grid.addColumn(new AdapterValueProvider(i)).setId(String.valueOf(i)).setWidth(60);
        }

        // wrap the data in "horizontal display adapters"
        grid.setItems(
                new HorizontalDisplayAdapter("Period", periods, PeriodSummary::getPeriod),
                new HorizontalDisplayAdapter("Workers", periods, PeriodSummary::getWorkers),
                new HorizontalDisplayAdapter("Newcomers", periods, PeriodSummary::getNewcomers),
                new HorizontalDisplayAdapter("Dismissals", periods, PeriodSummary::getDismissals)
        );

        // retrieve the correct period summary to edit, based on the column that was clicked (unless it's the header)
        grid.addItemClickListener(event -> {
            if (!ROW_CAPTION.equals(event.getColumn().getId())) {
                Integer columnIndex = Integer.valueOf(event.getColumn().getId());
                Notification.show("Editing " + event.getItem().getSummary(columnIndex), Notification.Type.ERROR_MESSAGE);
            }
        });

        // freeze first column for scrolling purposes
        grid.setFrozenColumnCount(1);

        addComponent(grid);
        setSizeFull();
    }

    // generate some dummy data to simulate loading from the DB
    private List<PeriodSummary> loadPeriods() {
        Random random = new Random();
        ArrayList<PeriodSummary> periodSummaries = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            periodSummaries.add(new PeriodSummary(i, random.nextInt(100), random.nextInt(100), random.nextInt(100)));
        }
        return periodSummaries;
    }

    // adapter to display data in a "horizontal format"
    public class HorizontalDisplayAdapter {
        // row caption
        private final String caption;

        // periods for each column
        private final List<PeriodSummary> periods;

        // used for brevity, a class hierarchy is probably more elegant
        private Function<PeriodSummary, Integer> valueExtractor;

        public HorizontalDisplayAdapter(String caption, List<PeriodSummary> periods, Function<PeriodSummary, Integer> valueExtractor) {
            this.caption = caption;
            this.periods = periods;
            this.valueExtractor = valueExtractor;
        }

        public String getCaption() {
            return caption;
        }

        public PeriodSummary getSummary(int columnIndex) {
            return periods.get(columnIndex);
        }

        // extract the data for a certain column
        public Integer getValue(int columnIndex) {
            return valueExtractor.apply(periods.get(columnIndex));
        }
    }

    // basic bean
    public class PeriodSummary {
        int period;
        int workers;
        int newcomers;
        int dismissals;

        public PeriodSummary(int period, int workers, int newcomers, int dismissals) {
            this.period = period;
            this.workers = workers;
            this.newcomers = newcomers;
            this.dismissals = dismissals;
        }

        public int getPeriod() {
            return period;
        }

        public void setPeriod(int period) {
            this.period = period;
        }

        public int getWorkers() {
            return workers;
        }

        public void setWorkers(int workers) {
            this.workers = workers;
        }

        public int getNewcomers() {
            return newcomers;
        }

        public void setNewcomers(int newcomers) {
            this.newcomers = newcomers;
        }

        public int getDismissals() {
            return dismissals;
        }

        public void setDismissals(int dismissals) {
            this.dismissals = dismissals;
        }

        @Override
        public String toString() {
            return "PeriodSummary{" +
                    "period=" + period +
                    ", workers=" + workers +
                    ", newcomers=" + newcomers +
                    ", dismissals=" + dismissals +
                    '}';
        }
    }

    // value provider for the horizontal display adapters
    private class AdapterValueProvider implements ValueProvider<HorizontalDisplayAdapter, Integer> {
        // column index is used to retrieve data from the correct summary
        private int columnIndex;

        public AdapterValueProvider(int columnIndex) {
            this.columnIndex = columnIndex;
        }

        @Override
        public Integer apply(HorizontalDisplayAdapter horizontalDisplayAdapter) {
            return horizontalDisplayAdapter.getValue(columnIndex);
        }
    }
}

<强>结果

"Horizontal" grid