在Excel中,如果按Tab键,则焦点会在相邻的方格中不断的跳转。
在SWT的Table或TableTree中,缺省情况下,是不支持这种通过Tab键的跳转的。如果能实现一个这样的功能,是不是很酷?
好,这里就教你这一招的实现,使用EditingSupport可以很容易的实现这个功能。
这里假设你实现的是一棵树表,并且这个树表要求至少包含SWT.FULL_SELECTION的样式。要求含Full_Selection样子主要是为了实现方便,因为full_selection样式支持鼠标在任意位置对表格的选中,否则只有在被选择行的表格才能被选中。
假如这个树已经通过增加EditingSupport实现了编辑支持。下面就是实现Tab键的跳转,实现如下:
思路:如果通过点击鼠标,很容易就让CellEditor出现,所以要实现Tab,我们可以通过模拟鼠标点击事件来实现。在SWT中,有两种实现模拟事件的方式,一种是通过Display的post()方法来实现,另一个是widget的notifyListener()方法来实现。这里我要用的notifyListener()。
首先给CellEditor的Control增加监听,如下:
cellEditor.getControl().addTraverseListener(this);
这里我记EditingSupport实现了TraverseListener,如下:
class FileEditingSupport extends EditingSupport implements TraverseListener
最后就是实现keyTraverse()方法,用来模拟鼠标事件:
public void keyTraversed(TraverseEvent e) { if(e.character!=SWT.TAB){ return; } Rectangle bound = cellEditor.getControl().getBounds(); Tree tree = (Tree) getViewer().getControl(); int x = bound.x+bound.width+2; int y = bound.y; if(index==tree.getColumnCount()-1){ x = tree.getColumn(0).getWidth()-2; y = y+bound.height+2; } Event origin = new Event(); origin.widget = tree; origin.x = x; origin.y = y; origin.display = tree.getDisplay(); origin.time = e.time; origin.count = 1; origin.type = SWT.MouseDown; origin.button = 1; tree.notifyListeners(SWT.MouseDown, origin); }
对于普通的TextCellEditor和ComboCellEditor,这样做是没什么问题的。不过如果你有一个DialogCellEditor,你就发现失灵的。这是因为DialogCellEditor的control是一个Composite,而得到焦点的是这个Composite上的Button,当你在这上按Tab的时候,是Button收到事件监听而不是底下的Composite得到事件。因为要让DialogCellEditor也能有此功能,我们要多做一点点事情。
思路:还是事件模拟,我们要让button上的事件转到control上。
实现如下:写一个抽象的DialogCellEditor类,主要是为了实现事件的跳转:
public abstract class TraverseDialogCellEditor extends DialogCellEditor implements TraverseListener { public TraverseDialogCellEditor() { super(); } public TraverseDialogCellEditor(Composite parent, int style) { super(parent, style); } public TraverseDialogCellEditor(Composite parent) { super(parent); } @Override protected Button createButton(Composite parent) { Button button = super.createButton(parent); button.addTraverseListener(this); return button; } public void keyTraversed(TraverseEvent e) { Event event = new Event(); event.time = e.time; event.character = e.character; getControl().notifyListeners(SWT.Traverse, event); } }
给button加上TraverseListener,所有它的事件再转到control上。
OK了。可以试试效果去了!