如何制作一个星云NatTable混合使用固定柱和一个剩余填充所有可用的垂直空间,其中,关键的是,固定宽度列冷用户可以调整大小?
视觉示例:
+-----------------------------------------+-------+-------+
| ...fills available vert space... | 100px | 100px |
用户通过将第0列和第1列之间的边框推到左侧来调整中间列的大小:
+---------------------------------------+----------+-------+
| ...fills available vert space... | 120px | 100px |
用户通过向左推动第1列和第2列之间的边框来调整第3列的大小:
+------------------------------------+----------+----------+
| ...fills available vert space... | 120px | 120px |
我非常接近这段代码:
IRowDataProvider<String> bodyDataProvider = ...;
DataLayer bodyDataLayer = new DataLayer(bodyDataProvider);
SelectionLayer selectionLayer = new SelectionLayer(bodyDataLayer, false);
ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
bodyDataLayer.setColumnPercentageSizing(0, true);
bodyDataLayer.setColumnPositionResizable(0, true);
bodyDataLayer.setColumnWidthByPosition(1, 100);
bodyDataLayer.setColumnPositionResizable(1, true);
bodyDataLayer.setColumnWidthByPosition(2, 100);
bodyDataLayer.setColumnPositionResizable(2, true);
它在视觉上实现了预期,它对容器(Shell)的反应也按照预期调整大小;固定列保持100px,只有第一列调整大小。到目前为止很好。但是存在一个问题:列间调整大小会发生一些不好的事情。我只是奇怪地做出反应。第0列和第1列之间的调整处理程序(标题边框)不会执行任何操作,只会显示调整大小但不会执行调整大小;第1列和第2列之间的大小调整处理器会做出反应,但只有第1列可以有效调整大小,第2列始终保持其大小,无论你做什么。
错误行为示例:您希望调整第2列(第3列)的大小,使其更大;你抓住第1列和第2列之间的边界,将边框拖到左边,意图通过有效地将第1列推到左边来使第2列更大。但是第2列保持不变,而第1列缩小了!
更新
我的问题是如何实现所需的行为。我需要设置或重新实现的内容和位置?自定义SizeConfig
?那里的方法听起来很有希望:calculatePercentages()
和calculateAvailableSpace()
。谁和什么时候打电话给他们?如何捕获列调整大小事件?我需要在某个地方设置听众吗?如何让NatTable使用自定义的SizeConfig
?
我是在正确的轨道上吗?
答案 0 :(得分:1)
我自己想通了。最后它并没有那么难。
所有必须做的就是注册一个自定义的ColumnResizeCommand
处理程序并实现它。
到NatTable创建代码块添加:
bodyDataLayer.registerCommandHandler(
new BetweenColumnResizeCommandHandler(bodyDataLayer));
它可以在任何地方,我只是在定义了列之后才有它
这会覆盖默认的BodyDataLayer
设置,该设置在方法中设置为默认类ColumnResizeCommandHandler
。寄存器是基于地图的,因此可以重复覆盖。寄存器将类命令类(表示事件)映射到给定层(事件/命令的终端消费者)的动作(处理程序)。
以下是BetweenColumnResizeCommandHandler
类的实现:
import org.eclipse.nebula.widgets.nattable.command.AbstractLayerCommandHandler;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.resize.command.ColumnResizeCommand;
import org.eclipse.nebula.widgets.nattable.resize.command.ColumnResizeCommandHandler;
/**
* Customised version of {@link ColumnResizeCommandHandler}.
*
* It implements "between" resizing mode, that is border is moved between two
* adjacent column only, having no effects on any other columns; that is any
* gain in size of the left side column is lost in size for right side column
* and vice versa.
*
* @author Espinosa
*/
public class BetweenColumnResizeCommandHandler extends AbstractLayerCommandHandler<ColumnResizeCommand> {
private final DataLayer dataLayer;
public BetweenColumnResizeCommandHandler(DataLayer dataLayer) {
this.dataLayer = dataLayer;
}
@Override
public Class<ColumnResizeCommand> getCommandClass() {
return ColumnResizeCommand.class;
}
@Override
protected boolean doCommand(ColumnResizeCommand command) {
int leftSideColumn = command.getColumnPosition();
int rightSideColumn = leftSideColumn + 1;
int oldLeftSideColumnWidth = this.dataLayer.getColumnWidthByPosition(leftSideColumn);
int newLeftSideColumnWidth = command.getNewColumnWidth();
int dragWidth = newLeftSideColumnWidth - oldLeftSideColumnWidth;
// dragWidth has to be re-calculated back because it is lost in ColumnResizeCommandHandler :(
int oldRightSideColumnWidth = this.dataLayer.getColumnWidthByPosition(rightSideColumn);
int newRightSideColumnWidth = oldRightSideColumnWidth - dragWidth;
this.dataLayer.setColumnWidthByPosition(leftSideColumn, newLeftSideColumnWidth);
if (rightSideColumn < this.dataLayer.getColumnCount()) {
this.dataLayer.setColumnWidthByPosition(rightSideColumn, newRightSideColumnWidth);
}
return true;
}
}
..并且它确实完全符合我的要求,如上例所示。
答案 1 :(得分:0)
你的问题是你正试图从右到左思考。但调整大小是从左到右实现的。因此,如果您采用第1列和第2列之间的边界,则需要调整第1列的大小,而不是第2列。方向无关紧要。
这是与众所周知的电子表格应用程序类似的行为。取边框之间的手柄会将列调整到左侧,而不是右侧。