#java #drag-and-drop #vaadin
#java #перетаскивание #vaadin
Вопрос:
У меня есть 3 таблицы в Vaadin:
Моя проблема сейчас в том, что перетаскивание не работает. Мой код следующий:
@Theme("valo")
@SpringView(name = TaskboardView.VIEW_NAME)
public class TaskboardView extends VerticalLayout implements View {
private enum TableType {
DONE, PROGRESS, OPEN;
}
private static final long serialVersionUID = 1L;
private final Logger logger = LoggerFactory.getLogger(TaskboardView.class);
public static final String VIEW_NAME = "taskboard";
// Components:
private SprintController sprintController = new SprintController();
private TaskController taskController = new TaskController();
private Sprint sprint;
private Set<Task> allTasks;
private List<Task> openTasks = new ArrayList<Task>();
private List<Task> inProgressTasks = new ArrayList<Task>();
private List<Task> doneTasks = new ArrayList<Task>();
// UI Components:
private Table openTable = new Table("Open Tasks:");
private int openTableId = 1;
private Table inProgressTable = new Table("Tasks in Progress");
private int inProgressTableId = 1;
private Table doneTable = new Table("Done Tasks");
private int doneTableId = 1;
private TextField sprintName = new TextField();
private OpenTableDropHandler openTableDropHandler = new OpenTableDropHandler();
private InProgressTableDropHandler inProgressTableDropHandler = new InProgressTableDropHandler();
DoneTableHandler doneTableHandler = new DoneTableHandler();
@PostConstruct
void init() {
logger.info("Initializing Taskboard View...");
try {
this.sprint = sprintController.getActiveSprint();
this.allTasks = sprintController.getTasksInSprint(this.sprint.getId().intValue());
sortSprintTasks(this.allTasks);
this.sprintName.setNullRepresentation("-- No active Sprint found --");
this.sprintName.setValue(this.sprint.getSprintName());
this.sprintName.setWidth("800px");
this.sprintName.setReadOnly(true);
this.sprintName.addStyleName("align-center"); // sets Allignment of
// the textfield!!!
} catch (NoActiveSprintReceivedException | NoSprintsExistException | IOException e) {
logger.error("Something went wrong initializing active Sprint. The taskboard can't be displayed.", e);
Notification.show("No Active Sprint found!", Notification.Type.ERROR_MESSAGE);
e.printStackTrace();
return;
} catch (TaskCanNotBeAllocatedException e) {
logger.error("Task of sprint couldn't be allocated to an status.", e);
Notification.show("Error! n n Task of sprint couldn't be allocated to an status.",
Notification.Type.ERROR_MESSAGE);
e.printStackTrace();
return;
}
// Layout for Sprint Name:
VerticalLayout headLayout = new VerticalLayout();
headLayout.setSpacing(true);
headLayout.setSizeFull();
;
headLayout.setMargin(true);
headLayout.addComponent(this.sprintName);
headLayout.setComponentAlignment(this.sprintName, Alignment.MIDDLE_CENTER);
setSizeFull();
setSpacing(true);
setMargin(true);
// Layout:
VerticalLayout verticalLayout = new VerticalLayout();
verticalLayout.setSpacing(true);
// Layout for Board:
HorizontalLayout taskBoardLayout = new HorizontalLayout();
taskBoardLayout.setSizeUndefined();
taskBoardLayout.setSpacing(true);
taskBoardLayout.setMargin(true);
// Adding to HorizontalLayout(TaskBoadLayout)
try {
initTable(this.openTable, TableType.OPEN);
initTable(this.inProgressTable, TableType.PROGRESS);
initTable(this.doneTable, TableType.DONE);
} catch (IOException e) {
logger.error("Something went wrong initizalizing Tables.");
Notification.show("Error! n n Couldn't initialize tables.", Notification.Type.ERROR_MESSAGE);
return;
}
taskBoardLayout.addComponent(openTable);
taskBoardLayout.addComponent(inProgressTable);
taskBoardLayout.addComponent(doneTable);
// Adding to VerticalLayout (MainLayout)
verticalLayout.addComponent(headLayout);
verticalLayout.addComponent(taskBoardLayout);
verticalLayout.setComponentAlignment(taskBoardLayout, Alignment.MIDDLE_CENTER);
addComponent(verticalLayout);
}
/**
* Sorts the tasks of the sprint to the required lists like open, in
* Progress, done.
*
* @param tasks
* @throws TaskCanNotBeAllocatedException
*/
private void sortSprintTasks(Set<Task> tasks) throws TaskCanNotBeAllocatedException {
logger.info("sortSprintTask(Set<Task>tasks): Sorting Tasks to the required lists...");
for (Task t : tasks) {
logger.info("Checking Sprint Status of Task >>>> " t.getHeadLine() " <<<<");
logger.info("Status: " t.getStatus());
if (t.getStatus().equals(WorkflowStatusConfigurator.open)) {
this.openTasks.add(t);
} else if (t.getStatus().equals(WorkflowStatusConfigurator.inProgress)) {
this.inProgressTasks.add(t);
} else if (t.getStatus().equals(WorkflowStatusConfigurator.done)) {
this.doneTasks.add(t);
} else {
throw new TaskCanNotBeAllocatedException(
"Task can't be allocated to a sprint status: " WorkflowStatusConfigurator.open ", "
WorkflowStatusConfigurator.inProgress ", " WorkflowStatusConfigurator.done ".");
}
}
}
@Override
public void enter(ViewChangeEvent event) {
// TODO Auto-generated method stub
}
/**
* Creates the tables depending on the type parameter
*
* @param table
* @param type
* @throws IOException
* @throws ClientProtocolException
*/
private void initTable(Table table, TableType type) throws ClientProtocolException, IOException {
table.setSelectable(true);
table.setImmediate(true);
table.setDragMode(TableDragMode.ROW);
table.addContainerProperty("ID", Long.class, null);
table.setColumnWidth("ID", 50);
table.addContainerProperty("Headline", String.class, null);
table.setColumnWidth("Headline", 300);
table.addContainerProperty("Task-Type", String.class, null);
table.setColumnWidth("Task-Type", 120);
table.addContainerProperty("Assignee", String.class, null);
table.setColumnWidth("Assignee", 100);
if (type.equals(TableType.OPEN) amp;amp; this.openTasks.size() > 0) {
logger.info("Loading values of Open Tasks Table...");
table.setDropHandler(this.openTableDropHandler);
for (Task t : this.openTasks) {
String assignee = this.taskController.getAssigneeInTask(t.getId().intValue()).getUserName();
table.addItem(new Object[] { t.getId(), t.getHeadLine(), t.getTaskType(), assignee }, this.openTableId);
this.openTableId ;
}
return;
}
if (type.equals(TableType.PROGRESS) amp;amp; this.inProgressTasks.size() > 0) {
logger.info("Loading values of Progress Tasks Table...");
table.setDropHandler(this.inProgressTableDropHandler);
for (Task t : this.inProgressTasks) {
String assignee = this.taskController.getAssigneeInTask(t.getId().intValue()).getUserName();
table.addItem(new Object[] { t.getId(), t.getHeadLine(), t.getTaskType(), assignee }, this.inProgressTableId);
this.inProgressTableId ;
}
return;
}
if (type.equals(TableType.DONE) amp;amp; this.doneTasks.size() > 0) {
logger.info("Loading values of Done Tasks Table...");
table.setDropHandler(this.doneTableHandler);
for (Task t : this.doneTasks) {
String assignee = this.taskController.getAssigneeInTask(t.getId().intValue()).getUserName();
table.addItem(new Object[] { t.getId(), t.getHeadLine(), t.getTaskType(), assignee }, this.doneTableId);
this.doneTableId ;
}
return;
}
}
private int giveEncreasedAvailableTableId(TableType tableType) {
if(tableType.equals(TableType.OPEN)){
this.openTableId ;
return this.openTableId;
}else if(tableType.equals(TableType.PROGRESS)){
this.inProgressTableId ;
return this.inProgressTableId;
}else if(tableType.equals(TableType.DONE)){
this.doneTableId ;
return this.doneTableId;
}else{
return -1;
}
}
private class OpenTableDropHandler implements DropHandler{
private static final long serialVersionUID = 1L;
private final Logger logger = LoggerFactory.getLogger(OpenTableDropHandler.class);
@Override
public void drop(DragAndDropEvent event) {
// Wrapper for the object that is dragged
logger.info("Received Drag and Drop Event from OpenTable...");
DataBoundTransferable t = (DataBoundTransferable) event.getTransferable();
AbstractSelectTargetDetails dropData = ((AbstractSelectTargetDetails) event.getTargetDetails());
Object itemId = t.getItemId();
Long id = (Long) t.getSourceContainer().getItem(itemId).getItemProperty("ID").getValue();
try {
Task taskToAdd = taskController.getById(id.intValue());
String author = taskController.getAuthorInTask(taskToAdd.getId().intValue()).getUserName();
if ( t.getSourceComponent() != openTable amp;amp; dropData.getTarget().equals(inProgressTable)) {
logger.info("Preparing Task Update to InProgress...");
openTable.addItem(new Object[] { taskToAdd.getId(), taskToAdd.getHeadLine(),
taskToAdd.getTaskType(), author, taskToAdd.getStatus() }, giveEncreasedAvailableTableId(TableType.OPEN));
openTasks.add(taskToAdd);
inProgressTable.removeItem(itemId);
inProgressTasks.remove(taskToAdd);
}else if(t.getSourceComponent() != openTable amp;amp; dropData.getTarget().equals(doneTable)){
logger.info("Preparing Task Update to Done...");
openTable.addItem(new Object[] { taskToAdd.getId(), taskToAdd.getHeadLine(),
taskToAdd.getTaskType(), author, taskToAdd.getStatus() }, giveEncreasedAvailableTableId(TableType.OPEN));
openTasks.add(taskToAdd);
doneTable.removeItem(itemId);
doneTasks.remove(taskToAdd);
}else{
logger.info("Do nothing...");
return;
}
taskToAdd.setStatus(WorkflowStatusConfigurator.open);
logger.info("Sending updates of taskboard to webservice...");
HttpResponse response = taskController.put(taskToAdd, taskToAdd.getId().intValue());
MainView.navigator.navigateTo(TaskboardView.VIEW_NAME);
// HttpResponse authorResponse = taskController.setAuthorInTask(taskToAdd.getAuthor().getId().intValue(),
// taskToAdd.getId().intValue());
// HttpResponse assigneeResponse = taskController.setAssigneeInTask(taskToAdd.getAssignee().getId().intValue(),
// taskToAdd.getId().intValue());
} catch (ClientProtocolException e) {
logger.warn("Something went wrong during Drag and Drop Process", e.getCause());
} catch (IOException e) {
logger.warn("Something went wrong during Drag and Drop Process", e.getCause());
}
}
@Override
public AcceptCriterion getAcceptCriterion() {
return AcceptAll.get();
}
}
private class InProgressTableDropHandler implements DropHandler{
private static final long serialVersionUID = 1L;
private final Logger logger = LoggerFactory.getLogger(InProgressTableDropHandler.class);
@Override
public void drop(DragAndDropEvent event) {
// Wrapper for the object that is dragged
logger.info("Received Drag and Drop Event from In Progress Table.");
DataBoundTransferable t = (DataBoundTransferable) event.getTransferable();
AbstractSelectTargetDetails dropData = ((AbstractSelectTargetDetails) event.getTargetDetails());
Object itemId = t.getItemId();
Long id = (Long) t.getSourceContainer().getItem(itemId).getItemProperty("ID").getValue();
try {
Task taskToAdd = taskController.getById(id.intValue());
String author = taskController.getAuthorInTask(taskToAdd.getId().intValue()).getUserName();
if (t.getSourceComponent() != inProgressTable amp;amp; dropData.getTarget().equals(doneTable) ){
inProgressTable.addItem(new Object[] { taskToAdd.getId(), taskToAdd.getHeadLine(),
taskToAdd.getTaskType(), author, taskToAdd.getStatus() }, giveEncreasedAvailableTableId(TableType.PROGRESS));
doneTable.removeItem(itemId);
inProgressTasks.add(taskToAdd);
doneTasks.remove(taskToAdd);
}else if(t.getSourceComponent() != inProgressTable amp;amp; dropData.getTarget().equals(openTable)){
inProgressTable.addItem(new Object[] { taskToAdd.getId(), taskToAdd.getHeadLine(),
taskToAdd.getTaskType(), author, taskToAdd.getStatus() }, giveEncreasedAvailableTableId(TableType.PROGRESS));
openTable.removeItem(itemId);
inProgressTasks.add(taskToAdd);
openTasks.remove(taskToAdd);
}else{
return;
}
logger.info("Sending updates of taskboard to webservice...");
taskToAdd.setStatus(WorkflowStatusConfigurator.inProgress);
HttpResponse response = taskController.put(taskToAdd, taskToAdd.getId().intValue());
MainView.navigator.navigateTo(TaskboardView.VIEW_NAME);
}catch (ClientProtocolException e) {
logger.warn("Something went wrong during Drag and Drop Process", e.getCause());
} catch (IOException e) {
logger.warn("Something went wrong during Drag and Drop Process", e.getCause());
}
}
@Override
public AcceptCriterion getAcceptCriterion() {
return AcceptAll.get();
}
}
private class DoneTableHandler implements DropHandler{
private static final long serialVersionUID = 1L;
private final Logger logger = LoggerFactory.getLogger(DoneTableHandler.class);
@Override
public void drop(DragAndDropEvent event) {
logger.info("Received Drag and Drop Event from In Done Table.");
DataBoundTransferable t = (DataBoundTransferable) event.getTransferable();
AbstractSelectTargetDetails dropData = ((AbstractSelectTargetDetails) event.getTargetDetails());
Object itemId = t.getItemId();
Long id = (Long) t.getSourceContainer().getItem(itemId).getItemProperty("ID").getValue();
try {
Task taskToAdd = taskController.getById(id.intValue());
String author = taskController.getAuthorInTask(taskToAdd.getId().intValue()).getUserName();
if (t.getSourceComponent() != doneTable amp;amp; dropData.getTarget().equals(inProgressTable) ){
doneTable.addItem(new Object[] { taskToAdd.getId(), taskToAdd.getHeadLine(),
taskToAdd.getTaskType(), author, taskToAdd.getStatus() }, giveEncreasedAvailableTableId(TableType.DONE));
inProgressTable.removeItem(itemId);
doneTasks.add(taskToAdd);
inProgressTasks.remove(taskToAdd);
}else if(t.getSourceComponent() != doneTable amp;amp; dropData.getTarget().equals(openTable)){
doneTable.addItem(new Object[] { taskToAdd.getId(), taskToAdd.getHeadLine(),
taskToAdd.getTaskType(), author, taskToAdd.getStatus() }, giveEncreasedAvailableTableId(TableType.DONE));
openTable.removeItem(itemId);
doneTasks.add(taskToAdd);
openTasks.remove(taskToAdd);
}else{
return;
}
logger.info("Sending updates of taskboard to webservice...");
taskToAdd.setStatus(WorkflowStatusConfigurator.done);
HttpResponse response = taskController.put(taskToAdd, taskToAdd.getId().intValue());
MainView.navigator.navigateTo(TaskboardView.VIEW_NAME);
}catch (ClientProtocolException e) {
logger.warn("Something went wrong during Drag and Drop Process", e.getCause());
} catch (IOException e) {
logger.warn("Something went wrong during Drag and Drop Process", e.getCause());
}
}
@Override
public AcceptCriterion getAcceptCriterion() {
return AcceptAll.get();
}
}
}
Есть ли у кого-нибудь идеи или хотя бы подсказки, почему это не работает? Я написал код, следуя тому же шаблону или способу, и он работал нормально. Единственное отличие в том, что там я не использую горизонтальную компоновку. И теперь таблица in Progress и Done не реагирует на перетаскивание строки на них.
Комментарии:
1. Я только что попробовал простой пример, похожий на ваш, и он отлично работает с Vaadin 7.7.3. Я предполагаю, что вы отфильтровываете удаленные данные в своих обработчиках в
else {return};
ветвях. Глядя наDoneTableHandler
это, я вижу `if (t.getSourceComponent() != doneTable amp;amp; dropData.getTarget().equals(inProgressTable) ){` что, я думаю, не совсем правильно. Обработчик удаления должен обрабатывать данные, удаленные из этого компонента, поэтому источником, вероятно, должны быть таблицы open или in progress , а целевой таблицей done .
Ответ №1:
Не по теме: почему у вас есть @Theme("valo")
представление? Насколько я знаю, это используется с UI
классом…
По теме:
Как я уже говорил в своем комментарии, я не думаю, что это связано HorizontalLayout
с. Возможно, вы неправильно поняли концепции перетаскивания источника и цели, или это просто проскользнуло в коде.
Как это также описано в документах, перетаскивание начинается с источника, а событие удаления данных на целевой объект обрабатывается a DropHandler
. Например, если вы посмотрите на свои исходные DoneTableHandler
тексты, вы увидите
if (t.getSourceComponent() != doneTable amp;amp; dropData.getTarget().equals(inProgressTable) ){
...
}else if(t.getSourceComponent() != doneTable amp;amp; dropData.getTarget().equals(openTable)){
...
}else{
return;
}
Поскольку вы прослушиваете drops на своем doneTable
, это будет target , а источниками может быть только openTable
or inProgressTable
, а не наоборот. У меня есть подозрение, что если вы собираетесь добавить строку журнала в else
ветку, вы увидите ее при каждом перетаскивании.
Ниже вы можете увидеть рабочий образец в Vaadin 7.7.3 с таблицами a HorizontalLayout
и 3, похожими на ваши. Это быстро и грязно, поэтому есть возможности для улучшения (предложения приветствуются), но (например: положение отброшенных элементов), он поддерживает многорядное перетаскивание, а также AcceptCriterion
фильтры удаляются из исходной таблицы или любого другого компонента, отличного от ожидаемых:
public class DragAndDropTables extends HorizontalLayout {
public DragAndDropTables() {
// leave some space between the tables
setSpacing(true);
// tables
Table toDoTable = createTable("To do");
Table inProgressTable = createTable("In progress");
Table doneTable = createTable("Done");
// drop handlers which allow only drops from expected sources
configureDragAndDrop(toDoTable, inProgressTable, doneTable);
configureDragAndDrop(inProgressTable, toDoTable, doneTable);
configureDragAndDrop(doneTable, toDoTable, inProgressTable);
// some table to make sure AcceptCriterion allows drops only from expected sources
Table tableNotAcceptableForDrops = createTable("Drops from here will not be accepted");
configureDragAndDrop(tableNotAcceptableForDrops);
tableNotAcceptableForDrops.addItem(new Task(100, "Not droppable task"));
// add some dummy data
for (int i = 0; i < 10; i ) {
toDoTable.addItem(new Task(i, "Task " i));
}
// add the tables to the UI
addComponent(toDoTable);
addComponent(inProgressTable);
addComponent(doneTable);
addComponent(tableNotAcceptableForDrops);
}
private Table createTable(String caption) {
// basic table setup
Table table = new Table(caption);
BeanItemContainer<Task> itemContainer = new BeanItemContainer<>(Task.class);
table.setContainerDataSource(itemContainer);
table.setMultiSelect(true);
table.setSelectable(true);
table.setPageLength(10);
return table;
}
private void configureDragAndDrop(Table table, Table... acceptedSources) {
// drag amp; drop configuration
table.setDragMode(Table.TableDragMode.MULTIROW);
table.setDropHandler(new DropHandler() {
@Override
public void drop(DragAndDropEvent event) {
// where the items are dragged from
Table source = (Table) event.getTransferable().getSourceComponent();
// where the items are dragged to
Table target = (Table) event.getTargetDetails().getTarget();
// unique collection of dragged tasks
HashSet<Task> draggedTasks = new HashSet<>();
// https://vaadin.com/api/com/vaadin/ui/Table.TableDragMode.html
// even in MULTIROW drag mode, the event contains only the row on which the drag started
draggedTasks.add((Task) event.getTransferable().getData("itemId"));
// we'll get the rest, if any, from the source table selection value
draggedTasks.addAll((Collection<Task>) source.getValue());
// remove items from source table
draggedTasks.forEach(((Table) source)::removeItem);
// add items to destination table
target.addItems(draggedTasks);
}
@Override
public AcceptCriterion getAcceptCriterion() {
// accept drops only from specified tables, and prevent drops from the source table
return new SourceIs(acceptedSources);
}
});
}
// basic bean for easy binding
public static class Task {
private String name;
private int id;
public Task(int id, String name) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
}
Результат: