¿Cómo detectar si se soltaron dos botones del mouse al mismo tiempo?

Estoy implementando el buscaminas y tengo un pequeño problema con el manejo de eventos del mouse. Quiero que las acciones se lleven a cabo en mouseRelease (no mousePressed), para que el usuario pueda cambiar de opinión después de presionar un botón del mouse. Hay tres acciones posibles:

  1. LMB liberado - revelar el campo actual
  2. RMB liberado - poner una bandera en el campo actual
  3. ambos LMB y RMB lanzados: resalte o revele campos adyacentes

Las acciones no son realmente importantes, lo que tengo problema es cómo desencadenarlas.

En los casos 1 y 2 no hay otros botones presionados; esto es fácil de verificar.

El problema es que soltar ambos botones da como resultado dos llamadas al método mouseRelease. Si hay un retraso demasiado grande entre la liberación de ambos botones, preferiría no activar una acción. En otras palabras, debería activarse solo si ambos botones se soltaron aproximadamente al mismo tiempo.

Puedo verificar fácilmente que, por ejemplo, el botón 3 está presionado cuando se suelta el botón 1, sin embargo, no es realmente útil.

Por el momento, no tengo otra idea que almacenar una hora en que se soltó el primer botón y luego compararla con la hora en que se soltó otro botón, y si la diferencia es lo suficientemente pequeña, desencadenar una acción.

Realmente no me gusta la idea de jugar con System.currentTimeMillis() o System.nanoTime() y me pregunto si hay una mejor manera de hacerlo.

SOLUCIÓN:

Lo que simplificó extremadamente el problema fue no permitir que el usuario arrastrara el puntero del mouse a otro campo (y, por lo tanto, cambiar el campo "seleccionado"). La demora entre soltar ambos botones no importa. Si el puntero del mouse va a otro campo, todo se borra. Aquí está el fragmento de código:

private static final int B1DM = MouseEvent.BUTTON1_DOWN_MASK;
private static final int B3DM = MouseEvent.BUTTON3_DOWN_MASK;

private boolean bothWereDown = false;

@Override
public void mousePressed(MouseEvent e) {

    // action if single button pressed
    // in my case this is a sub-action of pressing both buttons

    int both = B1DM | B3DM;
    bothWereDown = (e.getModifiersEx() & both) == both;

    if (bothWereDown) {
        // action if both buttons pressed
    }
}

@Override
public void mouseDragged(MouseEvent e) {

    // some other code

    if ( /* if pointer leaves field where mouse was pressed */) {
        // some other code
        bothWereDown = false;
        // some other code
    }
}

@Override
public void mouseReleased(MouseEvent e) {
    // some other code

    if (e.getButton() == MouseEvent.BUTTON1) {
        if (bothWereDown) {
            if ((e.getModifiersEx() & B3DM) != B3DM) {
                // action if both released
            }
        } else {
            // action if left button released
        }
    } else if (e.getButton() == MouseEvent.BUTTON3) {
        if (bothWereDown) {
            if ((e.getModifiersEx() & B1DM) != B1DM) {
                // action if both released
            }
        } else {
            // action if right button released
        }
    }

}

preguntado el 09 de marzo de 13 a las 14:03

1 Respuestas

La solución obvia es también rastrear las pulsaciones del mouse. No hay necesidad de jugar con los tiempos de espera en este caso, creo.

Por lo tanto, presionar ambos botones y luego soltar uno no contará como soltar un solo botón. De hecho, en su caso, probablemente no haría nada. Solo cuando se suelte también otro botón del mouse, eso contará como si se soltaran ambos botones.

Editar: en realidad, ni siquiera necesita realizar un seguimiento de las pulsaciones del mouse, aunque probablemente desee dar una indicación visual de que el botón está presionado, y soltarlo tendrá un efecto. Pero cuando se suelta el botón, y detecta que otro todavía está presionado, simplemente establezca una bandera que indica que se ha liberado la mitad de dos botones, y la liberación única de un botón lo completará. Si la bandera no está configurada en la liberación de un solo botón, entonces no es parte de la acción de dos botones y, en su lugar, realiza la acción de liberación de un solo botón.

respondido 09 mar '13, 14:03

En realidad, puede ser una buena idea ignorar este tiempo de espera. El comportamiento en este caso no está muy bien definido e incluso en el sistema buscaminas suceden algunas cosas extrañas. Entiendo que Swing no proporciona nada para manejarlo? - Jaroslaw pawlak

@JaroslawPawlak No sé nada específico relacionado con esto en Swing. Doubleclick es compatible con Swing, creo, pero distinguir los "acordes" de presionar muchos botones simultáneamente tendría que manejarlo usted mismo. Pero dado que está activando acciones solo en el lanzamiento, de hecho será más fácil, no es necesario ajustar el tiempo de espera difuso, etc. - Hyde

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.