当存在拖动源时,直到MouseUp才传递MouseDown事件 [英] MouseDown events are not delivered until MouseUp when a Drag Source is present

查看:112
本文介绍了当存在拖动源时,直到MouseUp才传递MouseDown事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个鼠标监听器。它具有一些代码来响应mouseUp和mouseDown事件。

I have a mouse listener. It has some code to respond to mouseUp and mouseDown events. This works correctly.

但是,一旦我添加了DragSource,我的mouseDown事件就不再传递了,直到释放鼠标按钮!

However, as soon as I add a DragSource, my mouseDown event is no longer delivered -- until I release the mouse button!

这很简单-下面是一个简单的程序,其中包含一个普通的外壳,只有一个鼠标侦听器和一个拖动侦听器。当我运行此程序(在Mac上)并按住鼠标按钮时,什么也没发生-但是,一旦松开鼠标按钮,我立即会看到同时发生的按下鼠标和按下鼠标事件。如果我注释掉拖动源,那么鼠标事件将以应有的方式传递。

This is trivial to reproduce - below is a simple program which contains a plain shell with just a mouse listener and a drag listener. When I run this (on a Mac), and I press and hold the mouse button, nothing happens - but as soon as I release the mouse button, I instantly see both the mouse down and mouse up events delivered. If I comment out the drag source, then the mouse events are delivered the way they should be.

我已经搜索了存在类似问题的其他对象,而最接近的是我们发现一个解释是这样的:

I've searched for others with similar problems, and the closest I've found to an explanation is this:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=26605#c16
如果您进行了拖动检测,操作系统需要吃掉鼠标事件直到它确定您是否拖动过。

https://bugs.eclipse.org/bugs/show_bug.cgi?id=26605#c16 "If you hook drag detect, the operating system needs to eat mouse events until it determines that you have either dragged or not."

但是,我不明白为什么会这样-操作系统为什么必须吃鼠标事件来确定是否我有没有阻力?直到我按下按钮时发生鼠标移动事件,阻力才开始。

However, I don't understand why that's true -- why must the operating system eat mouse events to determine if I have a drag or not? The drag doesn't start until I have a mouse -move- event with the button pressed.

更重要的是:有人可以建议解决方法吗? (我尝试在按下鼠标时动态添加和删除拖动源,但是后来我无法使拖放正常运行,因为它从未看到过初始按键-而且我找不到找到以编程方式启动的方法

More importantly: Can anyone suggest a workaround? (I tried dynamically adding and removing my drag source when the mouse is pressed, but then I couldn't get drag & drop to function properly since it never saw the initial key press - and I can't find a way to programmatically initiate a drag.)

这是示例程序:

    package swttest;

    import org.eclipse.swt.dnd.DND;
    import org.eclipse.swt.dnd.DragSource;
    import org.eclipse.swt.dnd.DragSourceEvent;
    import org.eclipse.swt.dnd.DragSourceListener;
    import org.eclipse.swt.events.MouseEvent;
    import org.eclipse.swt.events.MouseListener;
    import org.eclipse.swt.widgets.Display;
    import org.eclipse.swt.widgets.Shell;

    public class SwtTest {
        public static void main(String[] args) {
            final Display display = new Display();
            final Shell shell = new Shell(display);
            shell.addMouseListener(new MouseListener() {
                public void mouseUp(MouseEvent e) {
                    System.out.println("mouseUp");
                }

                public void mouseDown(MouseEvent e) {
                    System.out.println("mouseDown");
                }

                public void mouseDoubleClick(MouseEvent e) {
                    System.out.println("mouseDoubleClick");
                }
            });
            DragSourceListener dragListener = new DragSourceListener() {

                public void dragFinished(DragSourceEvent event) {
                    System.out.println("dragFinished");

                }

                public void dragSetData(DragSourceEvent event) {
                    System.out.println("dragSetData");

                }

                public void dragStart(DragSourceEvent event) {
                    System.out.println("dragStart");
                }
            };
            DragSource dragSource = new DragSource(shell, DND.DROP_COPY | DND.DROP_MOVE);
            dragSource.addDragListener(dragListener);
            shell.pack();
            shell.open();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch())
                    display.sleep();
            }
            display.dispose();
        }
    }


推荐答案

到回答您有关为什么发生这种情况的具体问题-在可可粉上,除非鼠标移动了几个像素,否则我们不认为开始拖动。如果您草率的点击,这可以确保避免意外拖动。在Linux和Win32上,窗口工具包可以执行拖动检测。如果仅按住按钮,则检测超时,并且按下鼠标。在Cocoa上我们没有超时,这就是为什么直到检测到拖动或鼠标悬停之前什么都没有发生的原因。

To answer your specific question about why this happens -- on Cocoa we don't consider a drag to have started until the mouse has moved a few pixels. This ensures against 'accidental' drags if you're sloppy with the clicks. On Linux and Win32 the window toolkit can do the drag detection. If you just hold down the button the detection times out and the mouse down is delivered. On Cocoa we have no time out, which is why nothing happens until the drag is detected or a mouse up happens.

这是很多细节,但是结论是行为不一致,因此我们应该始终能够立即将鼠标向下放,而不必等待拖动检测完成。

That's a lot of detail, but the conclusion is that the behavior is inconsistent, and we should always be able to deliver the mouse down immediately, without waiting for the drag detection to complete.

我没有看到解决方法,因为这是在控件看到事件之前发生的。

I don't see a workaround, since this is happening before the Control sees the event.

请参阅此错误,其中包含针对Win32,gtk的补丁和可可SWT。

See this bug which has patches for win32, gtk and cocoa SWT.

这篇关于当存在拖动源时,直到MouseUp才传递MouseDown事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆