问题描述
我正在尝试使用Spring Boot和Vaadin构建一个简单的Java应用程序.我需要在用户界面上添加一个表格,如下所示: https://www.screencast.com/t/1c4xkr4IE
I'm trying to build a simple java application using Spring Boot and Vaadin.I need to add a table on UI like this: https://www.screencast.com/t/1c4xkr4IE
它可以延长句点.
看起来像Vaadin Grid元素完全符合我的要求,但是它将我的行添加为列.是否可以反转网格,或者还有另一种方法来构建所需的表?
Looks like Vaadin Grid element perfectly fits my requirements, but it adds my rows as columns. Is it possible to reverse grid or maybe there is another way to build needed table?
更新
这是我的代码:
@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());
});
}
}
所以这个问题的意思是我设置了
So what I mean by this question is that I set
grid.setColumns("month", "numberOfWorkers", "numberOfNewcomers", "numberOfDismissals");
并没有找到类似setRows
的方法,因此我的表如下所示: https://www.screencast.com/t/ndDY6tXp ,但应该与第一张图片一样.
and do not find out method like setRows
, so my table looks like: https://www.screencast.com/t/ndDY6tXp, but should be like on first picture.
推荐答案
我相信Vaadin 网格(或表)组件的设计具有表格概念作为起点.因此,您将具有由列定义的统一结构,并显示任意数量的相同类型的数据元素,每行1个.据我所知,在8.0.4之前,您不能旋转该结构.
I believe the Vaadin grid (or table) component was designed having the table concept as a starting point. Hence you'd have a unified structure defined by the columns and display any number of same-type data elements, 1 per row. And as far as I know, up to 8.0.4, you can't rotate the structure.
此外,从用户体验的角度来看,如果您有多个时间段,则使用垂直(使用鼠标滚轮)滚动它们要比水平更容易,因此,建议您使用"month","numberOfWorkers","numberOfNewcomers"和"numberOfDismissals"列,并提供MyData
行,讨论在刚开始时显示它们的可能性.这也使排序,过滤,添加或编辑所选项目变得更加容易,而对于下面的解决方法,您将不得不做一些额外的事情.
Furthermore, from the user experience perspective, if you have multiple time periods, it'll be easier to scroll them vertically (with the mouse wheel) than horizontally, so I'd suggest discussing the possibility of displaying them just as you started, with the "month", "numberOfWorkers", "numberOfNewcomers" and "numberOfDismissals" columns, and supplying rows of MyData
. This also makes it easier to sort, filter, add or edit selected items, whereas for the workaround below, you'd have to do something extra.
如果由于某种原因根本无法接受,您应该可以通过一些工作来伪造所需的功能(请参见下面的示例),但是从性能和可用性的角度来看,我们无法保证...毕竟,这不是它的设计目的.
If for some reason that's not acceptable at all, you should be able to fake the feature you want with a bit of work (see below sample), but performance and usability wise, there's no guarantees... after all, this is not what it's been designed for.
代码
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);
}
}
}
结果
这篇关于如何反转vaadin Grid?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!