使用箭头键在TableViewers之间移动

时间:2012-05-24 22:54:17

标签: eclipse eclipse-rcp traversal tableviewer

我正在使用Eclipse 4.2 RC1开发e4 RCP应用程序。

我有一个控件(Composite),其中包含许多TableViewer个。观众垂直排列。如果用户在选择表的最后一个元素时按下向下箭头,我希望下一个表(下面)的第一个元素被选中。相反,如果选择了第一个元素并按下向上箭头,我希望选择上一个表格(上面)的最后一个元素。因为我的列设置,所​​以不可能使用单个TableViewer。在控件的初始化程序中调用以下函数,所有查看器都作为参数传递:

private void init(IEclipseContext context, IMDecisionTable input, DecisionTableTable...viewers) {
    for (int i = 0; i < viewers.length; i++) {
        viewers[i].hookMenuSupport(context);
        viewers[i].setInput(input);
        viewers[i].getTable().addTraverseListener(new TraverseSelector(
            i > 0 ? viewers[i-1] : null, i < viewers.length - 1 ? viewers[i+1] : null
        ));
    }
}

`TraverseSelector是我控件的嵌套类:

public class TraverseSelector implements TraverseListener {
    public DecisionTableTable p, n;

    public TraverseSelector(DecisionTableTable previous, DecisionTableTable next) {
        p = previous; n = next;
    }

    @Override public void keyTraversed(TraverseEvent e) {
        if (e.getSource() instanceof Table) {
            Table t = (Table) e.getSource();
            if (e.keyCode == SWT.ARROW_UP && p != null && t.getSelectionIndex() == 0) {
                select(p, -1, true);
                e.detail = SWT.TRAVERSE_NONE;
                e.doit = true;
                p.getTable().setFocus();
            } else if (e.keyCode == SWT.ARROW_DOWN && n != null && t.getSelectionIndex() == t.getItemCount() - 1) {
                select(n, 0, true);
                e.detail = SWT.TRAVERSE_NONE;
                e.doit = true;
                n.getTable().setFocus();
            }
        }
    }
}

满足条件时,它会尝试适当地设置选择。控件类中的其他相关代码:

private boolean selecting = false;
private ISelection selection = null;
@Override public ISelection getSelection() { return selection; }
@Override public void setSelection(ISelection sel, boolean reveal) {
    if (!selecting) {
        synchronized (this) { selecting = true; }
        selection = sel;
        for (TableViewer viewer : Arrays.asList(ftable, ctable, iatable, catable, pstable))
            viewer.setSelection(selection, reveal);
        synchronized (this) { selecting = false; }
    }
}
@Override public void selectionChanged(SelectionChangedEvent event) {
    if (!selecting) {
        synchronized (this) { selecting = true; }
        selection = event.getSelection();
        for (ISelectionProvider sp : Arrays.asList(ftable, ctable, iatable, catable, pstable))
            if (event.getSelectionProvider() != sp)
                sp.setSelection(null);
        synchronized (this) { selecting = false; }
    }
}
private void select(DecisionTableTable viewer, int index, boolean reveal) {
    Table t = viewer.getTable(); int count = t.getItemCount();
    setSelection(new StructuredSelection(t.getItem((index + count) % count).getData()), reveal);
}

我的困惑在于e.detail = SWT.TRAVERSE_NONE;e.doit = true;这两行。如果我删除这两个语句,事情就不起作用了。如果我删除那些和setFocus语句,则将选择设置为当前表的第一个或最后一个元素,在单个表中循环选择。在这些陈述之前,detaildoit分别为32和false。

2 个答案:

答案 0 :(得分:0)

我认为您的问题在于select(DecisionTableTable, int, boolean)方法。我不确定被覆盖的setSelection\selectionChanged方法的确切影响,但它们似乎过于复杂。你能不能通过以下方式达到你的要求:

private void select(DecisionTableTable viewer, int index, boolean reveal) {
    int count = viewer.getTable().getItemCount();
    viewer.setSelection(new StructuredSelection(viewer.getElementAt((index + count) % count), reveal);
}

此外,我认为您在切换表时应该设置doit=false,因为您不希望将事件应用于当前表。

答案 1 :(得分:0)

对我有用的是实现KeyListener而不是TransverseListener并在键监听器中添加行e.doit = false;。似乎某种事件传播引起了另一种选择,并且上面的行停止了传播。这是我的最终代码:

private boolean selecting;
private ISelection selection = null;
@Override public ISelection getSelection() { return selection; }
@Override public void setSelection(ISelection sel, boolean reveal) {
    if (!selecting) {
        synchronized (this) { selecting = true; }
        selection = sel;
        for (DecisionTableTable viewer : Arrays.asList(ftable, ctable, iatable, catable, pstable))
            viewer.setSelection(selection, reveal);
        synchronized (this) { selecting = false; }
    }
}
@Override public void selectionChanged(SelectionChangedEvent event) {
    if (!selecting) {
        synchronized (this) { selecting = true; }
        selection = event.getSelection();
        for (DecisionTableTable viewer : Arrays.asList(ftable, ctable, iatable, catable, pstable))
            if (event.getSelectionProvider() != viewer)
                viewer.setSelection(selection);
        synchronized (this) { selecting = false; }
    }
}

public class KeyHandler extends KeyAdapter {
    public DecisionTableTable p, n;

    public KeyHandler(DecisionTableTable previous, DecisionTableTable next) {
        p = previous; n = next;
    }

    @Override public void keyPressed(KeyEvent e) {
        if (e.getSource() instanceof Table) {
            Table t = (Table) e.getSource();
            if (e.keyCode == SWT.ARROW_UP && p != null && t.getSelectionIndex() == 0) {
                p.getTable().setFocus();
                p.setSelection(new StructuredSelection(p.getElementAt(p.getTable().getItemCount() - 1)));
                e.doit = false;
            } else if (e.keyCode == SWT.ARROW_DOWN && n != null && t.getSelectionIndex() == t.getItemCount() - 1) {
                n.getTable().setFocus();
                n.setSelection(new StructuredSelection(n.getElementAt(0)));
                e.doit = false;
            }
        }
    }
}