0

我在一个 SWT 应用程序中,可以Composite通过拖放重新排列 shell(或任何其他)内的控件。这基本上没有问题,DragSources和DropTargets都到位并相应地附加了听众。Transfer为了练习,我什至实现了一个自定义类型。很简单。

但是现在的要求是只有在执行拖动手势时按下 ALT 键才应该启动拖动,否则什么都不应该做。(ALT 键是一个示例,也可以是 CTRL。)

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

\1。拦截并取消DragDetect事件

这个想法是在没有按下 ALT 键的情况下取消事件event.doit = false

        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;
        }
        ...
    }

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

\3。结合 1 和 2

检查事件,将结果存储在某处,然后在事件中做出相应的stateMask反应。这不应该太难,但我认为它很难看,不应该这样做。代替,可以捕获 KeyUp/Down 事件并存储 ALT 键的最后一个已知状态。DragDetectDND.DragStartDragDetect

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

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

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

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

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

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

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

我在dragEnter,dragOverdragOperationChangedlistener 方法中有这个,这很好用。

4

1 回答 1

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();
}
于 2013-11-11T19:33:45.677 回答