我在SWT应用程序中,可以通过拖放操作重新排列shell(或任何Composite
)内的控件。这基本上没问题,DragSource
和DropTarget
都已到位,并且听众也相应地附加了。为了锻炼,我甚至实现了自定义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;
我在dragEnter
,dragOver
和dragOperationChanged
监听器方法中使用此方法,这非常正常。
答案 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();
}