How to use Nebula NatTable's PreserveSelectionModel?

北战南征 提交于 2019-12-12 03:08:17

问题


I am developing an RCP Application, and am using Nebula's NatTable for that. When it comes to selection, I am failing to understand how I am supposed to use it.

What I want is:

  • I want to have entire Rows selected. I was able do that using the RowOnlySelectionConfiguration and the RowOnlySelectionBindings.
  • If I select a row, I want the selection to stay there and not be cleared when some data in that row gets updated. How do I do that?
  • If a row is selected, and the position of the element in that row changes (e.g. one of the previous elements is removed, and the position changes to index - 1), I want the selection to change the position with the element, so that the same element is selected after the change. How do I do that?

I have seen that the documentation talks about a PreserveSelectionModel that can be used for that:

If you used the PreserveSelectionStructuralChangeEventHandler workaround in previous versions for not clearing the selection on structural changes, you will notice that this workaround will not work anymore. If you still need that behavior, you are now able to achieve the same by configuring and setting a SelectionModel instance like this:

SelectionModel model = new SelectionModel(selectionLayer); 
// configure to not clear the selection on structural changes 
model.setClearSelectionOnChange(false); 
selectionLayer.setSelectionModel(model);

If you expect that the selection should update and move with structural changes (e.g. sorting), try to use the PreserveSelectionModel.

https://www.eclipse.org/nattable/nandn/nandn_120.php

So I guess I have to use the PreserveSelectionModel? But there I can't call setClearSelectionOnChange(false). Does it do that by default?

And how do I use the PreserveSelectionModel? What do I pass in the constructor?

I implement my own BodyLayerStack, in a class called TableBodyLayerStack, where I tried this in the constructor:

public TableBodyLayerStack(IUniqueIndexLayer underlyingLayer) {
    super(underlyingLayer);
    columnReorderLayer = new ColumnReorderLayer(underlyingLayer);
    columnHideShowLayer = new ColumnHideShowLayer(columnReorderLayer);
    selectionLayer = new SelectionLayer(columnHideShowLayer, null, true, false);
    PreserveSelectionModel<?> selectionModel = new PreserveSelectionModel<>(
            selectionLayer, null, null);
    selectionLayer.setSelectionModel(selectionModel);
    selectionLayer.registerEventHandler(new SelectEventHandler(selectionLayer));
    viewportLayer = new ViewportLayer(selectionLayer);
    setUnderlyingLayer(viewportLayer);
    registerCommandHandler(new CopyDataCommandHandler(selectionLayer));
}

Then, in the contructor of my implementation of the GridLayer, I do this:

// ...

bodyLayer = new TableBodyLayerStack(eventLayer);
// register different selection move command handler that always moves by row
bodyLayer.getSelectionLayer().addConfiguration(new RowOnlySelectionConfiguration<T>());

// register selection bindings that will perform row selections instead of cell selections
// registering the bindings on a layer that is above the SelectionLayer will consume the
// commands before they are handled by the SelectionLayer
bodyLayer.addConfiguration(new RowOnlySelectionBindings());

// ...

But this is giving me NullPointerExceptions in the PreserveSelectionModel.

Error while painting table: null
java.lang.NullPointerException
at org.eclipse.nebula.widgets.nattable.selection.preserve.PreserveSelectionModel.getRowPositionByRowObject(PreserveSelectionModel.java:520)
at org.eclipse.nebula.widgets.nattable.selection.preserve.PreserveSelectionModel.createMarkerPoint(PreserveSelectionModel.java:559)
at org.eclipse.nebula.widgets.nattable.selection.preserve.PreserveSelectionModel.getSelectionAnchor(PreserveSelectionModel.java:531)
at org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.getSelectionAnchor(SelectionLayer.java:276)
at org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.getConfigLabelsByPosition(SelectionLayer.java:415)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getConfigLabelsByPosition(AbstractLayerTransform.java:316)
at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getConfigLabelsByPosition(AbstractIndexLayerTransform.java:318)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getConfigLabelsByPosition(CompositeLayer.java:553)
at org.eclipse.nebula.widgets.nattable.layer.cell.AbstractLayerCell.getConfigLabels(AbstractLayerCell.java:48)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayer.getCellPainter(AbstractLayer.java:354)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:336)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:336)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:336)
at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getCellPainter(AbstractIndexLayerTransform.java:340)
at org.eclipse.nebula.widgets.nattable.layer.AbstractLayerTransform.getCellPainter(AbstractLayerTransform.java:336)
at org.eclipse.nebula.widgets.nattable.layer.AbstractIndexLayerTransform.getCellPainter(AbstractIndexLayerTransform.java:340)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer.getCellPainter(CompositeLayer.java:586)
at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintCell(CellLayerPainter.java:171)
at org.eclipse.nebula.widgets.nattable.painter.layer.CellLayerPainter.paintLayer(CellLayerPainter.java:81)
at org.eclipse.nebula.widgets.nattable.painter.layer.GridLineCellLayerPainter.paintLayer(GridLineCellLayerPainter.java:106)
at org.eclipse.nebula.widgets.nattable.selection.SelectionLayerPainter.paintLayer(SelectionLayerPainter.java:95)
at org.eclipse.nebula.widgets.nattable.layer.CompositeLayer$CompositeLayerPainter.paintLayer(CompositeLayer.java:913)
at org.eclipse.nebula.widgets.nattable.painter.layer.NatLayerPainter.paintLayer(NatLayerPainter.java:43)
at org.eclipse.nebula.widgets.nattable.NatTable.paintNatTable(NatTable.java:408)
at org.eclipse.nebula.widgets.nattable.NatTable.paintControl(NatTable.java:403)
...

I guess it is because I pass null values in the constructor of my PreserveSelectionModel. But how do I use it instead? What do I have to pass as arguments for the constructor? Where do I get the values from?

Any help is appreciated.


回答1:


you are on the wrong track to achieve your goals. First I will answer your questions:

  1. So I guess I have to use the PreserveSelectionModel?

No, the PreserveSelectionModel is intended to preserve the selection for cell selections. You want to preserve the selection for whole rows. So you need to use the RowSelectionModel.

  1. But there I can't call setClearSelectionOnChange(false). Does it do that by default?

Yes

  1. But this is giving me NullPointerExceptions in the PreserveSelectionModel. I guess it is because I pass null values in the constructor of my PreserveSelectionModel.

Yes

  1. What do I have to pass as arguments for the constructor? Where do I get the values from?

The second parameter is IRowDataProvider<T>, so it is the IDataProvider for the body. The third parameter is IRowIdAccessor<T>. You need to create an implementation that provides an unique id, so a row can be identified without knowing the position or index in the underlying collection.

So what you need to do is something like this:

selectionLayer.setSelectionModel(new RowSelectionModel<Person>(
        selectionLayer, bodyDataProvider, new IRowIdAccessor<Person>() {

        @Override
        public Serializable getRowId(Person rowObject) {
            return rowObject.getId();
        }

    }));

But of course you need to provide the IDataProvider and also the IRowIdAccessor to your TableBodyLayerStack if you want to keep it generic.

Also note that you don't have to call SelectionLayer#registerEventHandler() yourself! This is done internally by calling SelectionLayer#setSelectionModel().

You can find several examples in the NatTable Examples Application at https://www.eclipse.org/nattable/ (the Try it! button on the right side). For your question the Tutorial Examples -> Layers -> Selection -> RowSelectionExample seems to be the one to look at.



来源:https://stackoverflow.com/questions/29212455/how-to-use-nebula-nattables-preserveselectionmodel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!