Jaroslaw Pawlak
Jaroslaw Pawlak

Reputation: 5578

How to detect if two mouse buttons were released at the same time?

I am implementing minesweeper and I have a little problem with handling mouse events. I want actions to take place on mouseRelease (not mousePressed), so the user can change his mind after pressing a mouse button. There are three possible actions:

  1. LMB released - reveal current field
  2. RMB released - put a flag in current field
  3. both LMB and RMB released - highlight or reveal adjacent fields

Actions are not really important, what I have problem with is how to trigger them.

In cases 1 and 2 no others buttons are down - this is easy to check.

The problem is that releasing both buttons results in two calls of mouseRelease method. If there is too large delay between both buttons releases I would prefer not to trigger an action. In other words, it should trigger only if both buttons were released at about the same time.

I can easily check that e.g. button 3 is down when button 1 is released, however it is not really helpful.

At the moment I have no other idea then storing a time when first button was released and then comparing it against the time when another button is released - and if the difference is small enough, trigger an action.

I do not really like an idea of playing with System.currentTimeMillis() or System.nanoTime() and I wonder whether there is a better way of doing it?

SOLUTION:

What has extremely simplified the problem was not allowing the user to drag a mouse pointer to another field (and hence changing the "selected" field). Delay between releasing both buttons does not matter. If the mouse pointer goes to another field, everything is cleared. Here is the code snippet:

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

}

Upvotes: 3

Views: 1185

Answers (1)

hyde
hyde

Reputation: 62797

Obvious solution is to also track mouse presses. No need to play around with timeouts in this case, I think.

So pressing both buttons, then releasing one, will not count as release of single button. In fact, in your case, it would probably do nothing. Only when also other mouse button gets released, that will then count as releasing both buttons.

Edit: Actually, you do not even need to track mouse presses, though you probably want to give visual indication that button is pressed, and releasing it will have an effect. But when button is released, and you detect other is still pressed, just set a flag that half of two button release has happened, and single release of one button will then complete it. If flag is not set on single button release, then it's not part of two button action, and you do the single button release action instead.

Upvotes: 4

Related Questions