NatTable 中的 RowSelection 与列组标题

问题描述

我创建了一个 Eclipse 应用程序,在其中使用单个列标题实现了 NatTable 的行选择。行选择工作正常。后来我向应用程序添加了一个带有列组标题的 NatTable。问题来了,单击单元格后,行选择不起作用。仅选择了单击的单元格。

我在 RowSelectionAction extends AbstractSelectionAction 类中定义了行选择。 RowSelectionAction 对象是在类 configureBodyMouseClickBindings() 的重写 extends DefaultSelectionBindings 方法中创建的。此方法在 NatTable.configure() 方法期间调用。但在使用列分组标题创建的 NatTable 中似乎没有调用 configureBodyMouseClickBindings() 方法。

以下是使用简单列标题创建 NatTable 的代码:

private NatTable createTable(Composite parent,List<TableLine> tLines,String[][] propertyNames,PropertyToLabels[] propToLabels,TableParams params,TextMatcherEditor<TableLine>editor) {

BodyLayerStack bodyLayerStack =
    new BodyLayerStack(
            tLines,new LineDataProviderColumnAccessor(propertyNames[0].length),params.getColumnIndicesForRowHeaders());

DataLayer bodyDataLayer = bodyLayerStack.getBodyDataLayer();
Integer[] rowHeights = params.getRowHeights();

if( rowHeights != null && rowHeights.length > 0 ) {
  for( int i = 0; i < rowHeights.length; i++ ) {
    if( rowHeights[i] != null )
      bodyDataLayer.setRowHeightByPosition(i,rowHeights[i]);
  }
}

Integer[] colWidths = params.getColumnWidths();
if( colWidths != null && colWidths.length > 0 ) {
  for( int i = 0; i < colWidths.length; i++ )
    if( colWidths[i] != null )
      bodyDataLayer.setColumnWidthByPosition(i,colWidths[i]);
}

IDataProvider columnHeaderDataProvider =
    new DefaultColumnHeaderDataProvider(propertyNames[0],propToLabels[0].getPropertyToLabels());
DataLayer columnHeaderDataLayer =
    new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);

ILayer columnHeaderLayer =
    new ColumnHeaderLayer(
        columnHeaderDataLayer,bodyLayerStack,(SelectionLayer)null);

Integer[] hrHeights = params.getHeaderRowHeights();
if( hrHeights != null && hrHeights.length > 0 )
  columnHeaderDataLayer.setRowHeightByPosition(0,hrHeights[0]);

CompositeLayer composite = new CompositeLayer(1,2);
composite.setChildLayer(GridRegion.COLUMN_HEADER,columnHeaderLayer,0);
composite.setChildLayer(GridRegion.BODY,1);

NatTable natTable = new NatTable(parent,composite,false);
natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
natTable.addConfiguration(new ContextMenuConfiguration(natTable));
natTable.addConfiguration(new AbstractRegistryConfiguration() {
  
  @Override
  public void configureRegistry(IConfigRegistry configRegistry) {
    Style cellStyle = new Style();
    cellStyle.setAttributeValue(
            CellStyleAttributes.BACKGROUND_COLOR,GUIHelper.COLOR_WIDGET_BACKGROUND);
    configRegistry.registerConfigAttribute(
            CellConfigAttributes.CELL_STYLE,cellStyle,DisplayMode.NORMAL,RowHeaderLabel);
  }
});
natTable.configure();

editor.setFilterator(new TextFilterator<TableLine>() {
  @Override
  public void getFilterStrings(List<String> baseList,TableLine element) {
    for( int i = 0; i < element.getLength(); i++ )
      baseList.add("" + element.getObjectByColumn(i));
  }
});
editor.setMode(TextMatcherEditor.REGULAR_EXPRESSION);
bodyLayerStack.getFilterList().setMatcherEditor(editor);

return natTable;}

BodyLayerStack.class 内容:

class BodyLayerStack extends AbstractLayerTransform {

private final FilterList<TableLine> filterList;
private final SelectionLayer selectionLayer;
private final DataLayer bodyDataLayer;
private final IRowDataProvider<TableLine> bodyDataProvider;

public DataLayer getBodyDataLayer() {
  return bodyDataLayer;
}

public SelectionLayer getSelectionLayer() {
  return selectionLayer;
}

public IRowDataProvider<TableLine> getBodyDataProvider() {
  return bodyDataProvider;
}

public BodyLayerStack(List<TableLine> values,IColumnAccessor<TableLine> columnAccessor,Integer[] columnIndicesForRowHeaders) {
    EventList<TableLine> eventList = GlazedLists.eventList(values);
    TransformedList<TableLine,TableLine> rowObjectsGlazedList = GlazedLists.threadSafeList(eventList);

    this.filterList = new FilterList<>(rowObjectsGlazedList);

    this.bodyDataProvider = new ListDataProvider<TableLine>(this.filterList,columnAccessor);
    bodyDataLayer = new DataLayer(this.bodyDataProvider);
    
    ColumnOverrideLabelAccumulator bodyLabelAccumulator = new ColumnOverrideLabelAccumulator(bodyDataLayer);
    bodyDataLayer.setConfigLabelAccumulator(bodyLabelAccumulator);

    if( columnIndicesForRowHeaders != null ) {
      for ( int i = 0; i < columnIndicesForRowHeaders.length; i++ ) {
        bodyLabelAccumulator.registerColumnOverrides(
            columnIndicesForRowHeaders[i],RowHeaderLabel);
      }
    }

    GlazedListsEventLayer<TableLine> glazedListsEventLayer =
            new GlazedListsEventLayer<>(bodyDataLayer,this.filterList);

    this.selectionLayer = new SelectionLayer(glazedListsEventLayer,false);
    selectionLayer.setSelectionModel(new RowSelectionModel<TableLine>(selectionLayer,this.bodyDataProvider,new IRowIdAccessor<TableLine>()
    {
      @Override
      public Serializable getRowId(TableLine line)
      {
        return line.getId();
      }
    }));

    selectionLayer.addConfiguration(new DefaultSelectionLayerConfiguration()
    {
      @Override
      protected void addSelectionUIBindings()
      {
        addConfiguration(new SelectionBindings());
      }

      @SuppressWarnings("rawtypes")
      @Override
      protected void addMoveSelectionConfig()
      {
        addConfiguration(new RowOnlySelectionConfiguration());
      }
    });

    ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
    setUnderlyingLayer(viewportLayer);
}

public FilterList<TableLine> getFilterList() {
    return this.filterList;
}

}

这是用于创建列组标题 NatTable 的代码:

private NatTable createTableWithColumnHeaderGroups(Composite parent,TextMatcherEditor<TableLine> editor) {
String[][] columnHeaders = params.getColumnHeaders();
if( columnHeaders == null || columnHeaders.length != 2 )
  return null;
String[] propertyNames = new String[columnHeaders[1].length];
PropertyToLabels propToLabels = new PropertyToLabels();
for( int i = 0; i < propertyNames.length; i++ ) {
  propertyNames[i] = String.valueOf(i+1) + "_" + columnHeaders[1][i];
  propToLabels.add(propertyNames[i],columnHeaders[1][i]);
}

BodyLayerStack bodyLayerStack =
    new BodyLayerStack(
            tLines,new LineDataProviderColumnAccessor(propertyNames.length),params.getColumnIndicesForRowHeaders());

ColumnGroupModel columnGroupModel = new ColumnGroupModel();

IRowDataProvider<TableLine> bodyDataProvider =
    new ListDataProvider<TableLine>(tLines,new LineDataProviderColumnAccessor(propertyNames.length));
ColumnGroupBodyLayerStack bodyLayer =
    new ColumnGroupBodyLayerStack(bodyLayerStack.getBodyDataLayer(),columnGroupModel);

Integer[] rowHeights = params.getRowHeights();
if( rowHeights != null && rowHeights.length > 0 ) {
  for( int i = 0; i < rowHeights.length; i++ ) {
    if( rowHeights[i] != null )
      bodyLayer.doCommand(new RowResizeCommand(bodyLayer,i,rowHeights[i]));
  }
}
Integer[] colWidths = params.getColumnWidths();
if( colWidths != null && colWidths.length > 0 ) {
  for( int i = 0; i < colWidths.length; i++ )
    if( colWidths[i] != null )
      bodyLayer.doCommand(new ColumnResizeCommand(bodyLayer,colWidths[i]));
}

// Column header
DefaultColumnHeaderDataProvider defaultColumnHeaderDataProvider =
    new DefaultColumnHeaderDataProvider(propertyNames,propToLabels.getPropertyToLabels());
DefaultColumnHeaderDataLayer columnHeaderDataLayer =
    new DefaultColumnHeaderDataLayer(defaultColumnHeaderDataProvider);
ColumnHeaderLayer columnHeaderLayer =
    new ColumnHeaderLayer(columnHeaderDataLayer,bodyLayer,bodyLayer.getSelectionLayer());
ColumnGroupHeaderLayer columnGroupHeaderLayer =
    new ColumnGroupHeaderLayer(
        columnHeaderLayer,bodyLayer.getSelectionLayer(),columnGroupModel);

Integer[] hrHeights = params.getHeaderRowHeights();
if( hrHeights != null && hrHeights.length > 0 )
  for( int i = 0; i < hrHeights.length; i++ )
    if( hrHeights[i] != null )
      columnGroupHeaderLayer.doCommand(new RowResizeCommand(columnGroupHeaderLayer,hrHeights[i]));

List<ColumnHeaderGroup> groups = params.getColumnHeaderGroups();
for( ColumnHeaderGroup group : groups ) {
  List<Integer> indices = group.getIndices();
  int[] indicesArray = new int[indices.size()];
  for( int i = 0; i < indices.size(); i++ )
    indicesArray[i] = indices.get(i);
  columnGroupHeaderLayer.addColumnsIndexesToGroup(group.getName(),indicesArray);
}

// Row header
final DefaultRowHeaderDataProvider rowHeaderDataProvider =
    new DefaultRowHeaderDataProvider(bodyDataProvider);
DefaultRowHeaderDataLayer rowHeaderDataLayer =
    new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
ILayer rowHeaderLayer =
    new RowHeaderLayer(rowHeaderDataLayer,bodyLayer.getSelectionLayer());

// Corner
final DefaultCornerDataProvider cornerDataProvider =
    new DefaultCornerDataProvider(defaultColumnHeaderDataProvider,rowHeaderDataProvider);
DataLayer cornerDataLayer =
    new DataLayer(cornerDataProvider);
ILayer cornerLayer =
    new CornerLayer(cornerDataLayer,rowHeaderLayer,columnGroupHeaderLayer);

// Grid
GridLayer gridLayer =
    new GridLayer(bodyLayer,columnGroupHeaderLayer,cornerLayer);

NatTable natTable = new NatTable(parent,gridLayer,false);

editor.setFilterator(new TextFilterator<TableLine>() {

  @Override
  public void getFilterStrings(List<String> baseList,TableLine element) {
    for( int i = 0; i < element.getLength(); i++ )
      baseList.add("" + element.getObjectByColumn(i));
  }
});
editor.setMode(TextMatcherEditor.REGULAR_EXPRESSION);
bodyLayerStack.getFilterList().setMatcherEditor(editor);

natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
natTable.addConfiguration(new ContextMenuConfiguration(natTable));
natTable.addConfiguration(new AbstractRegistryConfiguration() {
  
  @Override
  public void configureRegistry(IConfigRegistry configRegistry) {
    Style cellStyle = new Style();
    cellStyle.setAttributeValue(
            CellStyleAttributes.BACKGROUND_COLOR,RowHeaderLabel);
  }
});
natTable.configure();
return natTable;  }

最终,问题可能出在具有两行列标题创建的 nat 表的 nat 表层实现中。

解决方法

问题出在您的代码中。在带有 ColumnGroupHeader 的版本中,您创建了两个 body 层堆栈。首先是您还显示的 BodyLayerStack。但是那个不用于列组示例。在那里您使用名为 ColumnGroupBodyLayerStack 的第二个。由于未显示该类,我无法判断该类是否缺少行选择配置。但可能是这样,因为 NatTable 层实现中没有关于该功能的问题。

顺便说一句,我建议使用 NatTable 1.6 引入的性能列分组,而不是旧的基于 ColumnGroupModel 的实现。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...