2010-10-11 13 views
17

Tengo un detector de mouse. Tiene algún código para responder a los eventos mouseUp y mouseDown. Esto funciona correctamenteLos eventos MouseDown no se entregan hasta MouseUp cuando hay una fuente de arrastre

Sin embargo, tan pronto como agregue un DragSource, mi evento mouseDown ya no se entrega, ¡hasta que suelte el botón del mouse!

Esto es trivial de reproducir: a continuación se muestra un programa simple que contiene un shell simple con solo un detector de mouse y un detector de arrastre. Cuando ejecuto esto (en una Mac), y mantengo presionado el botón del mouse, no pasa nada, pero tan pronto como suelto el botón del mouse, instantáneamente veo los eventos del mouse hacia abajo y el mouse hacia arriba entregados. Si hago un comentario sobre la fuente de arrastre, los eventos del mouse se entregan como deberían.

He buscado otras personas con problemas similares, y el más cercano que he encontrado para una explicación es la siguiente:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=26605#c16 "Si gancho remolque detecta, el sistema operativo tiene que comer los eventos del ratón hasta que se determina que has arrastrado o no ".

Sin embargo, no entiendo por qué es cierto: ¿por qué el sistema operativo debe comer los eventos del mouse para determinar si tengo un arrastre o no? El arrastre no se inicia hasta que tengo un evento mouse -move- con el botón presionado.

Lo más importante: ¿Alguien puede sugerir una solución? (Intenté agregar y eliminar dinámicamente mi origen de arrastre cuando se presiona el mouse, pero luego no pude obtener la función de arrastrar & para que funcione correctamente, ya que nunca vi presionar la tecla inicial, y no puedo encontrar la manera de iniciar programáticamente un . arrastre)

Aquí está el programa de ejemplo:

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(); 
     } 
    } 
+0

Lo he intentado y su código funciona en Windows. Podría ser el error – nanda

+0

específico del sistema operativo. Acabo de probar esto en Ubuntu 10.04 y funciona bastante bien. Presiona el botón izquierdo del mouse para obtener ningún evento. Mueva el mouse para obtener 'mouseDown' y' dragStart' * al mismo tiempo *. Cuando lo dejas, obtienes el evento 'mouseUp'. Si mantienes el mouse quieto y presionas el botón izquierdo, obtienes un 'mouseDown' después de un notable retraso de 1-2 segundos. De cualquier manera, 'mouseDown' siempre se ve antes de soltar el mouse. Debe ser un problema SWT en Mac? – richq

+0

Gracias a ambos: parece que esto es definitivamente específico de la plataforma. Sin embargo, parece que también está bastante roto en Linux: un retraso de un segundo antes de que se entregue mouseDown no funcionará, ya que el motivo por el que trato de cambiar el manejo de mouseUp a mouseDown es hacer que la interfaz de usuario se sienta más receptiva. –

Respuesta

8

para responder a su pregunta específica sobre por qué sucede esto - el cacao no consideramos un lastre que han comenzado hasta que el ratón se ha movido unos pocos píxeles . Esto asegura contra los arrastres "accidentales" si está descuidado con los clics. En Linux y Win32, el toolkit de ventana puede hacer la detección de arrastre. Si mantiene presionado el botón, la detección expira y el mouse se entrega. En Cocoa no tenemos tiempo de espera, por lo que no ocurre nada hasta que se detecta la resistencia o se produce un movimiento de mouse.

Eso es un montón de detalles, pero la conclusión es que el comportamiento es inconsistente, y siempre deberíamos ser capaces de soltar el mouse inmediatamente, sin esperar a que se complete la detección de arrastre.

No veo una solución alternativa, ya que esto está sucediendo antes de que el Control vea el evento.

Ver this bug que tiene parches para win32, gtk y cocoa SWT.

+0

¡Guau! Un parche, para todas las plataformas, ¡no menos, dentro de un día o dos! ¡Impresionante! ¡Gracias! –

+0

Aparentemente, el MouseDown retrasado durante un arrastre es intencional. Para aquellos que juegan en casa, por favor mire el error Eclipse antes mencionado para más detalles. –

1

Tuve el mismo problema y encontré una solución. Una vez que conecte un DragSource a su widget personalizado, el bucle de evento se bloqueará en el gancho del mouse de ese widget y comerá eventos de movimiento del mouse para detectar un arrastre. (Solo he examinado el código GTK de SWT para descubrirlo, por lo que puede funcionar un poco diferente en otras plataformas, pero mi solución funciona en GTK, Win32 y Cocoa.) En mi situación, no era tanto interesado en detectar el evento de mouse justo cuando sucedió, pero estaba interesado en reducir significativamente el retraso de detección de arrastre, ya que el objetivo de mi implementación Canvas era que el usuario arrastrara cosas.Para desactivar el bloqueo bucle de eventos y funciones de detección de arrastre, todo lo que tiene que hacer es:

setDragDetect(false); 

En mi código, yo estoy haciendo esto antes de colocar el DragSource. Como ya has señalado, esto te dejará con el problema de que ya no puedes iniciar un arrastre. Pero también he encontrado una solución para eso. Afortunadamente, la generación del evento de arrastre es puramente Java y no específica de la plataforma en SWT (solo es la detección de arrastre). De modo que puede generar su propio evento DragDetect en el momento que le resulte más conveniente. He adjuntado un MouseMoveListener a mi Canvas, y almacena la última posición del mouse, la distancia de arrastre acumulada y si ya generó o no un evento DragDetect (entre otras cosas útiles). Esta es la implementación mouseMove():

public void mouseMove(MouseEvent e) { 
    if (/* some condition that tell you are expecting a drag*/) { 

     int deltaX = fLastMouseX - e.x; 
     int deltaY = fLastMouseY - e.y; 

     fDragDistance += deltaX * deltaX + deltaY * deltaY; 

     if (!fDragEventGenerated && fDragDistance > 3) { 
      fDragEventGenerated = true; 

      // Create drag event and notify listeners. 
      Event event = new Event(); 
      event.type = SWT.DragDetect; 
      event.display = getDisplay(); 
      event.widget = /* your Canvas class */.this; 
      event.button = e.button; 
      event.stateMask = e.stateMask; 
      event.time = e.time; 
      event.x = e.x; 
      event.y = e.y; 
      if ((getStyle() & SWT.MIRRORED) != 0) 
       event.x = getBounds().width - event.x; 

      notifyListeners(SWT.DragDetect, event); 
     } 
    } 

    fLastMouseX = e.x; 
    fLastMouseY = e.y; 
} 

Y que reemplazará al, bloqueando la detección de arrastre incorporado para usted.

Cuestiones relacionadas