SWT:影响Drag& Drop手势的检测(或:如何查询键盘)

时间:2013-11-11 17:19:11

标签: java drag-and-drop swt

我在SWT应用程序中,可以通过拖放操作重新排列shell(或任何Composite)内的控件。这基本上没问题,DragSourceDropTarget都已到位,并且听众也相应地附加了。为了锻炼,我甚至实现了自定义Transfer类型。很简单。

但现在要求的是,只有在执行拖动手势时按下ALT键才能启动拖动,否则不应执行任何操作。 (ALT键是一个例子,也可以是CTRL。)

到目前为止,我看到或已经考虑过以下方法。所有这些都不起作用或丑陋。

\ 1。拦截并取消DragDetect事件

如果未使用event.doit = false按下ALT键,则可以取消该事件。

        lblPos.addListener(SWT.DragDetect, new Listener() {
            public @Override void handleEvent(Event event) {
                if ((event.stateMask & SWT.ALT) == 0)
                    event.doit = false;     // XXX: doit will not be evaluated
            }
        });

然而,这不起作用。 doit标志显然未被评估。

\ 2。拦截并取消DND.DragStart事件。

    class RowDragListener implements DragSourceListener {
        public @Override void dragStart(DragSourceEvent event) {
            if (/* ALT key not pressed */) 
                event.doit = false;
        }
        ...
    }

这与appraoch 1的问题相反。虽然doit标志被正确评估并因此适合取消拖动,但在可以检查修改键的情况下没有stateMask。所以问题出现了,如何直接查询键盘(不安装KeyUp / Down事件处理程序)? ALT键的当前上/下状态是什么?

\ 3。合并1和2

检查stateMask事件中的DragDetect,将结果存储在某处,然后在DND.DragStart事件中作出相应的反应。这不应该太难,但我认为这很难看,不应该这样做。可以捕获KeyUp / Down事件而不是DragDetect,并且存储ALT密钥的最后已知状态。

\ 4。覆盖Control.dragDetect(Event)Control.dragDetect(MouseEvent)

如果这些方法看到满足条件的话,最终会创建DragDetect个事件。

检查事件的stateMask并仅在发出所需的修饰键时发出超类中的重写方法。这里的问题是,从文档中不清楚这是否是在拖动手势上处理的唯一代码路径。实际上,这两种方法彼此独立(它们不相互调用),因此甚至不清楚要覆盖哪一种方法。这些方法已经是两种不同的方式来启动拖动手势。谁知道有多少种方式?如果可能的话,覆盖它们将是容易出错的,并且当然不会干净。

所以我的问题是: 你会怎么做?还有其他想法吗? 2.如果方法2看起来最合理,那么在不诉诸事件处理程序的情况下如何查询键盘?

(很抱歉这篇文章的格式化,我似乎无法掌握语法。或者也许这不是我的错,谁知道。)

更新:有一点需要注意,我在实施过程中注意到了这一点。在Windows上,ALT-Drag& Drop具有链接操作的特定含义(与移动或复制相反; cmp.DND.DROP_ *常量)。这就是为什么,如果你选择以类似的方式使用ALT键,建议在DropTargetListener的每个合理场合包括以下行。

 if (event.detail == DND.DROP_LINK) event.detail = DND.DROP_MOVE;

我在dragEnterdragOverdragOperationChanged监听器方法中使用此方法,这非常正常。

1 个答案:

答案 0 :(得分:1)

您可以收听SWT.DragDetect事件,检查状态掩码并仅在满足条件时创建拖动源。然后通过调用notifyListeneres()将事件传递给新创建的拖动源。拖动完成后,必须处理拖动源。

这是一个片段,只有在按下alt时才启动拖动,并使用文本作为传输:

public static void main(String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display);
    shell.setLayout(new GridLayout());

    shell.addListener(SWT.DragDetect, new Listener() {
        @Override
        public void handleEvent(Event event) {
            if ((event.stateMask & SWT.ALT) != 0) {
                final DragSource dragSource = new DragSource(shell, DND.DROP_MOVE);
                dragSource.addDragListener(new DragSourceAdapter(){
                    @Override
                    public void dragFinished(DragSourceEvent event) {
                        dragSource.dispose();
                    }

                    @Override
                    public void dragSetData(DragSourceEvent event) {
                        event.data = "text";
                    }
                });
                dragSource.setTransfer(new Transfer[]{TextTransfer.getInstance()});
                dragSource.notifyListeners(SWT.DragDetect, event);

            }
        }
    });

    shell.open();
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }
    display.dispose();
}