上下文
我已经实现了一个NatTable (v1.1.0.201405012245) --请考虑以下简化示例:
package testproject;
import java.util.ArrayList;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.nebula.widgets.nattable.NatTable;
import org.eclipse.nebula.widgets.nattable.config.AbstractRegistryConfiguration;
import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
import org.eclipse.nebula.widgets.nattable.config.EditableRule;
import org.eclipse.nebula.widgets.nattable.config.IConfigRegistry;
import org.eclipse.nebula.widgets.nattable.data.IColumnAccessor;
import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
import org.eclipse.nebula.widgets.nattable.edit.EditConfigAttributes;
import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditBindings;
import org.eclipse.nebula.widgets.nattable.edit.config.DefaultEditConfiguration;
import org.eclipse.nebula.widgets.nattable.edit.editor.TextCellEditor;
import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
import org.eclipse.nebula.widgets.nattable.layer.LabelStack;
import org.eclipse.nebula.widgets.nattable.layer.cell.IConfigLabelAccumulator;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
import org.eclipse.nebula.widgets.nattable.selection.config.DefaultSelectionStyleConfiguration;
import org.eclipse.nebula.widgets.nattable.style.DisplayMode;
import org.eclipse.nebula.widgets.nattable.viewport.ViewportLayer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
public class ViewPart1 extends ViewPart
{
@Override
public void createPartControl(final Composite parent)
{
final ArrayList<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
final IColumnAccessor<String> columnAccessor = new IColumnAccessor<String>()
{
@Override
public void setDataValue(final String rowObject, final int columnIndex, final Object newValue)
{
if (!(newValue instanceof String) || ((String) newValue).contains("x"))
{
MessageDialog.openError(getSite().getShell(), "Error", "Invalid Input");
return;
}
list.set(list.indexOf(rowObject), (String) newValue);
}
@Override
public Object getDataValue(final String rowObject, final int columnIndex)
{
return rowObject;
}
@Override
public int getColumnCount()
{
return 1;
}
};
final IDataProvider dataProvider = new ListDataProvider<>(list, columnAccessor);
final DataLayer dataLayer = new DataLayer(dataProvider);
final SelectionLayer selectionLayer = new SelectionLayer(dataLayer);
final ViewportLayer viewportLayer = new ViewportLayer(selectionLayer);
final NatTable table = new NatTable(parent, viewportLayer, false);
GridDataFactory.fillDefaults().grab(true, true).applyTo(table);
viewportLayer.addConfiguration(new DefaultEditConfiguration());
viewportLayer.addConfiguration(new DefaultEditBindings());
viewportLayer.setRegionName(GridRegion.BODY);
viewportLayer.setConfigLabelAccumulator(new IConfigLabelAccumulator()
{
@Override
public void accumulateConfigLabels(final LabelStack configLabels, final int columnPosition, final int rowPosition)
{
configLabels.addLabel("myLabel");
}
});
table.setConfigRegistry(new ConfigRegistry());
table.addConfiguration(new DefaultNatTableStyleConfiguration());
table.addConfiguration(new DefaultSelectionStyleConfiguration());
table.addConfiguration(new AbstractRegistryConfiguration()
{
@Override
public void configureRegistry(final IConfigRegistry registry)
{
registry.registerConfigAttribute(EditConfigAttributes.CELL_EDITOR, new TextCellEditor(true), DisplayMode.NORMAL, "myLabel");
registry.registerConfigAttribute(EditConfigAttributes.CELL_EDITABLE_RULE, EditableRule.ALWAYS_EDITABLE, DisplayMode.NORMAL, "myLabel");
}
});
table.configure();
}
@Override
public void setFocus()
{
}
}当然,这不是真正的代码,但是我的问题也可以用这个代码来演示。
重要的是,在我的实际项目中,当用户修改一个值时,我需要更新一个模型(包括一个复杂的依赖树),如果它失败了(例如,在数值计算中,更改会导致除法为零),我需要显示一个错误(并恢复到以前的值)。
为了显示我的核心问题,在这里显示的代码中,我检查IColumnAccessor#setDataValue中的一个简单条件(输入包含一个'x'),并相应地显示错误。
问题
我的实际问题是,如果您在TextCellEditor中输入x,错误对话框会弹出两次(按顺序--即当我单击第一个对话框确定时,第二个对话框将显示)。
分析
我的分析表明,原因是setDataValue被调用了两次:
- `TextCellEditor(AbstractCellEditor).commit(SelectionLayer$MoveDirectionEnum, boolean) line: 331`
- `TextCellEditor(AbstractCellEditor).commit(SelectionLayer$MoveDirectionEnum) line: 326`
- `TextCellEditor$1.keyPressed(KeyEvent) line: 246`
- `TextCellEditor(AbstractCellEditor).commit(SelectionLayer$MoveDirectionEnum, boolean, boolean) line: 341`
- `TextCellEditor(AbstractCellEditor).commit(SelectionLayer$MoveDirectionEnum, boolean) line: 331`
- `AbstractCellEditor$InlineFocusListener.focusLost(FocusEvent) line: 462`
因此,我的主要问题是:我如何预防(或至少检测到)第二个事件?
发布于 2015-08-07 15:26:09
您的实现的问题是,您正在IColumnAccessor中执行一个转换,并打开一个对话框通知用户错误。但是,由于使用了各种用例,这并不是使用NatTable的方法。
如果需要执行转换和/或验证,则应该注册适当的IDisplayConverter和IDataValidator。由于您需要一个字符串,所以不需要注册不同的转换器,因为通过DefaultEditConfiguration注册的默认转换器已经在注册了。所以,您需要的是一个IDataValidator,它检查值x,在这种情况下抛出一个ValidationFailedException。如果将DialogErrorHandling注册为验证错误处理程序,则带有异常消息的错误将显示在对话框中。不打开对话框两次的检查是在内部完成的。
这在(目前较小的)文档http://www.eclipse.org/nattable/documentation.php?page=editing中得到了解释。
顺便说一句,我建议更新最新的NatTable版本1.3.0,因为它还包含几个BTW。
https://stackoverflow.com/questions/31878482
复制相似问题