Удалить несколько строк из Nattable

Я пытаюсь удалить более одной строки из NatTable. Следуя решению, описанному в разделе Удалить строки из Nattable. Я создал следующие классы: класс Command выглядит так:

public class DeleteMultiRowCommand extends AbstractMultiRowCommand {

    public DeleteMultiRowCommand(AbstractMultiRowCommand command) {
        super(command);
    }

    protected DeleteMultiRowCommand(ILayer layer, int[] rowPositions) {
        super(layer, rowPositions);
    }

    @Override
    public ILayerCommand cloneCommand() {
        return new DeleteMultiRowCommand(this);
    }

}

Класс обработчика команд:

public class DeleteMultiRowCommandHandler<T> implements ILayerCommandHandler<DeleteMultiRowCommand> {

    private List<T> bodyData;
    private SelectionLayer layer;

    public DeleteMultiRowCommandHandler(List<T> bodyData, SelectionLayer selectionLayer) {
        this.bodyData = bodyData;
        this.layer = selectionLayer;
    }

    public DeleteMultiRowCommandHandler(List<T> bodyData){
        this.bodyData = bodyData;
    }

    @Override
    public Class<DeleteMultiRowCommand> getCommandClass() {
        return DeleteMultiRowCommand.class;
    }

    @Override
    public boolean doCommand(ILayer targetLayer, DeleteMultiRowCommand command) {
        //convert the transported position to the target layer
        if (command.convertToTargetLayer(targetLayer)) {
            Collection<Integer>rowpos = command.getRowPositions();
            //remove the element
            for(Integer val : rowpos){
                this.bodyData.remove(val.intValue());
                targetLayer.fireLayerEvent(new RowDeleteEvent(targetLayer, val.intValue()));
            }

            return true;
        }
        return false;
    }

}

и команда будет запущена при нажатии на элемент меню

this.contextMenu = new PopupMenuBuilder(natTable)
            .withInspectLabelsMenuItem()
            .withClearAllFilters()
            .withColumnRenameDialog()
            .withMenuItemProvider(new IMenuItemProvider() {

                @Override
                public void addMenuItem(final NatTable natTable, Menu popupMenu) {
                    MenuItem deleteRow = new MenuItem(popupMenu, SWT.PUSH);
                    deleteRow.setText("Delete Row(s)");
                    deleteRow.setEnabled(true);

                    deleteRow.addSelectionListener(new SelectionAdapter() { 
                        @Override
                        public void widgetSelected(SelectionEvent event) {
                            //int rowPosition = MenuItemProviders.getNatEventData(event).getRowPosition();
                            ILayer bl = ((GridLayer)natTable.getLayer()).getBodyLayer();
                            BodyLayerStack bl1 = (BodyLayerStack) bl;
                            SelectionLayer sl = bl1.getSelectionLayer();
                            int []poss = new int[sl.getFullySelectedRowPositions().length];
                            int i=0;
                            for(int pos1 : sl.getFullySelectedRowPositions()){
                                poss[i]=sl.getRowIndexByPosition(pos1);
                                i++;
                            }
                            //System.out.println("Menu item selected "+rowPosition);
                            //natTable.doCommand(new DeleteRowCommand(natTable, rowPosition));
                            natTable.doCommand(new DeleteMultiRowCommand(natTable, poss));
                        }
                    });
                }
            })
            .build();

когда я пытаюсь удалить строки, строки, которые не выбраны, удаляются. Похоже, проблема с преобразованием позиции строки в индекс строки. правильно ли преобразование позиции строки в индекс строки в пределах моего IMenuItemProvider?


person ssdimmanuel    schedule 04.08.2016    source источник


Ответы (2)


Похоже, вы делаете преобразование из позиции в индекс дважды: один раз в прослушивателе выбора пункта меню и один раз в обработчике команд (вызывая convertToTargetLayer). Первое не нужно.

person Arye Shemesh    schedule 04.08.2016
comment
ранее я не использовал getRowIndexByPosition, но это вызывало ту же проблему удаления какой-либо другой строки. - person ssdimmanuel; 04.08.2016

Это не проблема NatTable, а проблема работы с коллекциями. Вам нужно удалить элементы в обратном порядке, если вы удаляете элементы один за другим. В противном случае элементы для индексов изменяются во время обработки.

Предположим, вы хотите удалить элементы с индексом 1 и 2. После удаления элемента с индексом 1 элементы ниже переместятся вверх. Таким образом, элемент, который был раньше по индексу 2, теперь будет по индексу 1, а элемент по индексу 3 будет по индексу 2. Поэтому удаление элемента по индексу 2 на следующей итерации удалит элемент, который раньше был по индексу. 3.

Я бы предложил отсортировать и отменить коллекцию индексов, прежде чем повторять удаление элементов из коллекции. Чем это должно работать.

person Dirk Fauth    schedule 05.08.2016
comment
Я изменил свой метод Commandhandler doCommand, чтобы сохранить выбранные объекты во временном ArrayList, а затем удалить методом ArrayList.remove(Object). Но все же проблема возникает. У меня также есть строка фильтра. Я также мог заметить, что метод command.convertToTargetLayer(targetLayer) возвращает false, если я пытаюсь удалить первую строку. - person ssdimmanuel; 05.08.2016
comment
Если проблема все еще присутствует при таком подходе, вы работаете с неправильным списком. Я предполагаю, что таблица показывает содержимое списка фильтров, но вы работаете с базовым списком. Вы должны убедиться, что вы работаете с одним и тем же экземпляром списка. - person Dirk Fauth; 05.08.2016
comment
Вот как я создаю CommandHandler: List data = ((ListDataProvider)bodyLayerStack.getBodyDataProvider()).getList(); bodyLayerStack.getBodyDataLayer().registerCommandHandler(new DeleteRowCommandHandler(data,bodyLayerStack.getSelectionLayer())); bodyLayerStack.getBodyDataLayer().registerCommandHandler(new DeleteMultiRowCommandHandler(data)); Я использую FilterList для создания BodyDataProvider. - person ssdimmanuel; 05.08.2016
comment
Извините, но я не могу удаленно отлаживать ваш код. Что-то у вас не так с составом касаемо коллекций. Вам необходимо отлаживать и проверять коллекции и их содержимое по сравнению с тем, что вы хотите удалить. - person Dirk Fauth; 05.08.2016
comment
Если я не использую getRowIndexByPosition (как предложил @Arye Shemesh), кажется, что удаление работает для всех строк, кроме 1-й и 2-й строк. Теперь команда выглядит так natTable.doCommand(new DeleteMultiRowCommand(natTable, sl.getFullySelectedRowPositions()));. Еще нужно выяснить, почему 1-ю и 2-ю строки нельзя удалить. - person ssdimmanuel; 05.08.2016
comment
Я изменил new DeleteMultiRowCommand(natTable, selectionLayer.getFullySelectedRowPositions()) на new DeleteMultiRowCommand(selectionLayer, selectionLayer.getFullySelectedRowPositions()). Теперь удаления работают нормально. - person ssdimmanuel; 05.08.2016